Authorization comes first
Selo sends no request to a route unless a verified, unexpired authorization covers its exact origin, path and method. The address rules below apply on top of that: even an authorized URL is refused if it points at a private network.Target URL rules
Every target URL, and every redirect hop Selo is allowed to follow, must pass these rules before any DNS lookup.
The fragment is dropped; the query string is kept.
Blocked address ranges
After DNS resolution, every resolved address is classified. Selo connects only if every address in the answer is public.
For IPv6:
- Any address outside
2000::/3(global unicast) is blocked. That covers::1loopback,::unspecified,fc00::/7unique local,fe80::/10link-local andff00::/8multicast. 2001::/32(Teredo) and2001:db8::/32(documentation) are blocked.- IPv4-mapped (
::ffff:a.b.c.d), IPv4-compatible, NAT64 (64:ff9b::/96) and 6to4 (2002::/16) addresses are judged by the IPv4 address they embed. - Any address with a zone index (
%eth0) is blocked.
DNS resolution and pinning
Checking a hostname and then letting the HTTP client resolve it again would leave a gap: a DNS rebinding attack can answer the second lookup with a private address. Selo closes that gap:- It resolves the hostname once and collects every address in the answer. An empty answer is a network failure.
- It refuses the request if any address is not public.
- It connects to the first vetted address through a connector pinned to that hostname and address. The connector refuses to resolve any other hostname.
- TLS still validates the certificate against the hostname, so pinning does not weaken HTTPS.
- Each redirect hop is resolved, classified and pinned again from scratch.
Redirects
When Selo follows a redirect, each hop must pass every URL rule and stay on the same origin, and Selo strips
authorization, cookie, proxy-authorization, payment-signature and x-payment from the request. A 301, 302 or 303 becomes a GET without a body.
Time and size limits
A body that announces a
content-length over the limit is refused before it is read; a streamed body is cut off as soon as it passes the limit.
Spend caps
A job can spend at most 0.50 USDC paying your endpoint, and no configuration can raise a job’s budget above 5.00 USDC. The budget is enforced by one conditional database update in the same transaction that records the payment, with CHECK constraints as a backstop, and any payment with an unclear outcome stops all further spending for the job. See Payments and spend limits.Secrets never reach evidence or logs
Selo redacts in two layers. A secret is replaced bysha256: followed by the hex SHA-256 of its value, so you can still match it against a value you hold without Selo keeping it.
Layer 1: headers at capture
When Selo records a response’s headers, it replaces the values ofauthorization, proxy-authorization, cookie, set-cookie (each cookie separately), payment-signature and x-payment with their hash. The signed payment header that Selo sends is never stored; evidence keeps only its hash.
Layer 2: every stored or logged value
Every value written to evidence, scenario records, the evidence packet and alerts passes through a sanitizer:- Secret keys. A field whose name, lowercased with
_and-removed, isauthorization,proxyauthorization,cookie,setcookie,xpayment,paymentsignature,sk,sig,accesstoken,refreshtoken,idtoken,apikeyorbearer, or containsmnemonic,secret,privatekey,password,passphraseorsignature, has its value hashed (strings) or replaced by[redacted](anything else). Anauthorizationfield that holds an object, such as an authorization snapshot, is sanitized field by field instead. - Secret values anywhere. Inside any string, a base64 token of 40 or more characters that decodes to a signed Algorand transaction, or to JSON that contains a secret, is hashed.
- Wallet phrases. A run of 24 or more words of which at least 90% are Algorand mnemonic words is hashed, even with a mistyped word or inside longer text.
- Bounds. Strings are truncated at 4,096 characters after secrets are hashed, and nesting is cut at depth 12.
The test
A22: logs, evidence, reports and the evidence packet contain no wallet secret runs a full paid release test, then searches stdout, stderr, the evidence table, the API response, the report and the evidence packet for any three consecutive words of the mnemonic of Selo’s operating wallet, which signs the downstream payment, and for every signed payment header. None may appear.Report links are private
Each report lives athttps://api.useselo.xyz/v1/reports/<token>:
- The token is an HMAC-SHA256 of the job id under a server secret of at least 32 characters, encoded as 43 base64url characters. It cannot be guessed from the job id.
- Selo stores only the SHA-256 of the token. A database copy does not reveal any report link.
- The route serves only jobs whose report is written. An unknown and a malformed token get the same
404answer. - Every answer carries
X-Robots-Tag: noindex, nofollow,Cache-Control: private, no-storeandReferrer-Policy: no-referrer.
<private> and writes the same redacted form into gate summaries; the full link is kept only in the local run file under .selo/runs/.
The CLI and your wallet
Theselo CLI pays Selo from the wallet in SELO_PAYER_MNEMONIC. Use a dedicated payer wallet that holds only what you are willing to spend.
- The mnemonic is read from the environment and never printed or written to disk; neither is the signed payment or the report token.
- On Mainnet, the CLI refuses to pay without
--approve-mainnetand the--pay-toaddress you expect Selo to use. It checks both before sending any request. - It refuses before signing if Selo’s price is above
--max-usdcor Selo’s402names a network other than--network. - It never retries a payment on its own. If an outcome is unconfirmed, it records the attempt in
.selo/runs/<release>.jsonand refuses to pay again until you resume. - With
GITHUB_STEP_SUMMARYset, it appends a sanitized summary of the gate decision.
What Selo stores
Selo never stores your mnemonic (the CLI never sends it), the signed payment header, the report token or the verification token.
Related
Authorization
How a route is authorized and when Selo re-checks it.
Payments and spend limits
The budget invariant and the payment states.
Known limitations
What Selo does not do yet.
Output files
The run file, the gate summary and the attestation the CLI writes.