Farbeam

Security

This page describes what the Farbeam application does, based on its source code. It lists the weak points as well. The service has had no third-party audit, and it holds no security certification. The docs have a shorter developer note.

#Wallet sign-in and sessions

An account is a Solana address. There is no password and no email. Reading the API needs no account. EVM wallet sign-in is Planned.

StepWhat happens
ChallengePOST /auth/challenge returns a text message with a random nonce. It expires in 5 minutes and works once
SignatureThe wallet signs the text. This sends no transaction and costs nothing. The server never sees a private key
VerifyPOST /auth/verify checks the ed25519 signature against the address, and deletes the nonce
SessionA random token in the cookie fb_session. The database holds only its SHA-256 hash, and it expires after 7 days
Sign-outPOST /auth/logout deletes the session row and clears the cookie

The cookie has HttpOnly, SameSite=Strict and Path=/api, and Secure over HTTPS. Page scripts cannot read it, and browsers do not send it on requests from other sites. Sign-in attempts are limited to 30 per hour per network.

The account row holds the address, the created and last-seen times, and a linked Telegram chat id if you link one. A signature proves control of the address at that moment and nothing more. A person who controls the wallet controls the account. Removing the Telegram link is DELETE /account/telegram.

#API keys

PropertyBehaviour
Formatfbk_ plus 24 random bytes in hex
StorageSHA-256 hash of the key. The key itself is never stored
ShownOnce, in the response to POST /keys
RecoveryNot possible. Create a new key
IdentityBelongs to the signed-in account. A label you choose, cut to 60 characters
Stored with the hashKey id, label, created time, last-used time, calls per UTC day
SendingAuthorization: Bearer <key> or x-api-key
RevokingDELETE /keys/{id} in a session, or DELETE /me with the key. The record stays in the database
Limit5 active keys per account, 20,000 units per UTC day per key

The console does not store a key in the browser. It uses the session cookie, and the server uses a hidden key of the account for limits and rule ownership. Do not put a key in client-side code that other people can read.

#Webhook secrets

Each rule has a signing secret: fbs_ plus 24 random bytes in hex. It is returned once, when the rule is created. The API never returns it again.

Unlike API keys, signing secrets are stored in readable form in the database, because the server needs the value to compute each HMAC. Someone with access to the database file could read them and forge signatures. There is no rotate endpoint. To replace a secret, delete the rule and create a new one.

Signatures use HMAC-SHA256 over <t>.<raw body>. Verify the signature and check t so an old request cannot be replayed. See webhook signatures.

#Webhook SSRF protection

Rule URLs point at hosts chosen by users, so the server treats them as hostile. Checks run when a rule is saved and again on every delivery.

CheckRule
Schemehttps only
Port443 only
Credentials in URLRefused
HostIP literals refused. localhost, .local and .internal names refused
DNSEvery resolved address must be public. If any address is private, the delivery is refused
ConnectionUses the address that was checked, so a second DNS answer cannot change the target
RedirectsNot followed
Timeout6 seconds
LengthURL up to 500 characters

Refused IPv4 ranges: private ranges (RFC 1918), loopback, link-local, carrier-grade NAT, benchmark ranges, multicast and reserved ranges.

The response body from your endpoint is not read or stored. The delivery log keeps the HTTP code and a short error class.

#Rule language

Beamline expressions are parsed by a small hand-written compiler into closures. The code never calls eval. A rule can have up to 1,000 characters and 64 conditions.

#Contact messages

Messages from the contact form contain name, email, optional company, topic and message. They are written to the database first, then forwarded to the inbox for contact@farbeamlabs.com. Failed sends retry every minute, up to 50 times. After a send, the content in the database is replaced with an empty object, and the row is deleted after 30 days. If forwarding keeps failing, the content stays in the database until someone handles it.

The form allows 3 messages per network per 10 minutes.

#Logs

The application writes no request logs. It does not store IP addresses on disk.

DataWhere it is heldFor how long
SHA-256 hash of the client IP, for rate limitsMemoryUp to about 6 minutes
SHA-256 hash of the client IP, for key creation and contact limitsMemoryUp to 24 hours after the last event, or until a restart
SHA-256 hash of the client IP, for open stream countsMemoryWhile the stream is open
Method, path and error text of an unexpected server errorProcess outputAs kept by the host

A hash of an IPv4 address can be reversed by trying all addresses, which is one reason these values stay in memory. The error output can contain a path, and a path can contain an address or a transaction hash. It does not contain the IP or the key.

This table covers the application. A network provider or hosting layer between you and the application can see connection data, as with any website.

#HTTP headers

Pages and API responses from the application have these headers.

HeaderValue
content-security-policydefault-src 'self'; img-src 'self' data:; style-src 'self'; script-src 'self'; connect-src 'self'; font-src 'self'; media-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'
x-content-type-optionsnosniff
x-frame-optionsDENY
referrer-policyno-referrer
permissions-policygeolocation=(), camera=(), microphone=()

The policy blocks inline scripts and third-party scripts, styles and fonts. Fonts are self-hosted. The site uses no third-party analytics. The only cookie is fb_session, set after a wallet sign-in. API responses add cache-control: no-store and access-control-allow-origin: *. The API is meant to be called from any origin, so never rely on CORS to protect a key. The session cookie is SameSite=Strict, so a request from another site does not carry it.

#Request handling

#What the service never does

Farbeam does not hold funds and does not ask a wallet to sign a transaction. The console asks a Solana wallet to sign one text message for sign-in. That message says that it sends no transaction and costs nothing. The site never asks for a seed phrase or a private key. If anyone claims otherwise in the name of Farbeam, treat it as a scam and report it.

#Reporting a problem

Use the contact form with the topic "Security report", or write to contact@farbeamlabs.com.

Please include:

Please test only against your own keys and rules. Do not read other users' data, do not run load tests, and do not send spam through the contact form. Give a reasonable time to fix a problem before you publish it. There is no paid bounty program.