Security at Settlens
Settlens is a security tool, so its own limits are part of the product. Here is what it never does, how its tests are gated, how we handle your data, how the site is run and how to report a vulnerability.
settlens scan http://127.0.0.1:4402/secure --active
Settlens error: Active testing requires --authorized to confirm explicit owner approval.
settlens scan http://127.0.0.1:4402/secure \
--active --authorized
Settlens error: Active testing requires --authorization-ref with a traceable owner approval reference.
settlens scan http://127.0.0.1:4402/secure \
--active --authorized \
--authorization-ref PILOT-0001 --no-write
Settlens x402 assessment 996014c8
Targets 1 · Active 1 · Settlement calls 0
15 pass · 0 fail · 0 warn · 0 skip
In short
Settlens never pays, never creates a valid payment, never holds wallet or payment keys and never calls a facilitator's /settle. Scans are passive by default; the one active probe needs three explicit flags and the owner's written authorization. Vulnerabilities are reported privately by email.
What Settlens never does
These limits are enforced in the code, not left to configuration. They hold for the CLI, the GitHub Action, the container, the API and the MCP server.
-
Never pays or signs
No Settlens tool creates a valid payment. The only signature it ever sends is an intentionally invalid one, and only in an authorized active probe.
-
Never holds your keys or funds
No wallet, no payment key, no custody. The only key in play is a separate ed25519 evidence key, held by whoever signs the report (you, or Settlens for a pilot), and Settlens uses it only to sign report attestations.
-
Never calls /settle
Settlens reads a facilitator's /supported and, in an authorized probe, sends one invalid payload to /verify. Settlement is never requested.
-
Never sends your PAYMENT-SIGNATURE
A PAYMENT-SIGNATURE header supplied in a target or on the command line is refused before any request, so a real authorization cannot leak into a scan.
-
Never follows redirects
A 3xx answer is reported as a finding with the sanitized Location; the payment challenge is only assessed at the URL you named.
-
Never stores response bodies
Bodies are read up to 1 MiB to bound memory; reports keep only their size and SHA-256 digest. Request header values are omitted and URL credentials redacted.
Passive by default, active only with authorization
A passive scan only reads what any unauthenticated client would see. The single active test needs three explicit flags, and the CLI stops with exit code 2 if one is missing.
| Behavior | Passive scan | Active probe |
|---|---|---|
| Default mode | ||
| Sends a payment header | One intentionally invalid PAYMENT-SIGNATURE | |
| Requires the owner's written authorization and a reference | ||
| Calls the facilitator's /verify | With the same invalid payload | |
| Calls the facilitator's /settle | ||
| Needs a wallet or private key | ||
| Available over the MCP server |
Read the methodology for what each result proves, and the terms of use for the authorization rules.
How we handle pilot data
We ask for as little as possible, and an assessment never needs your secrets.
Pilot requests
The pilot form collects a name, work email, company and message. Requests are stored on our server, hosted by IONOS SE in the European Union, read only by the publisher, and a daily clean-up deletes requests more than 12 months old. Our replies come from the contact@settlens.com mailbox, hosted by Hostinger. Details are in the privacy notice.
Assessments
- We need URLs and the payment terms you expect, not credentials. Passive scans send no authentication.
- If a staging endpoint needs a header, it is only sent to hosts you allowlist with
--allow-host; otherwise the CLI refuses to run. Values can come from environment variables and are never written into reports. - Pilots run on test networks, synthetic data and staging endpoints where possible, with at most two passive samples and one authorized invalid-signature probe per run.
- We stop immediately if you withdraw the authorization or if any unexpected impact appears.
Reports
Reports omit response bodies and request header values, redact URL credentials and secret query parameters (such as api_key, token or signature), and carry a deterministic SHA-256 integrity block. You can verify them, and the signed attestation, offline. See reports and evidence.
Never send us secrets
Private keys, seed phrases, third-party bearer tokens, real PAYMENT-SIGNATURE values and customer data have no place in a pilot request, a report or a support email. To check a captured PAYMENT-SIGNATURE that is still valid, run verify-payment or the local MCP server instead of sending it to us or pasting it into the browser verifier.
The remote MCP endpoint
https://settlens.com/mcp serves the Settlens tools to AI agents over MCP Streamable HTTP, and the free browser tools call it too. Here is what limits a public caller.
-
Offline tools are public
The six public tools compute only on the inputs you send: payment-request evaluation, signature, transaction, report and attestation checks, and the check catalog.
-
Network tools need a token
scan_endpoint and scan_facilitator are listed and callable only with a Settlens API token, compared in constant time. They are passive; the active probe is not available over MCP.
-
Public destinations only
Before any remote network request, private, loopback, link-local and other non-public addresses are rejected, including through DNS answers, and only ports 80 and 443 are allowed. Redirects are never followed.
-
Hardened transport
POST only (plus CORS preflight), JSON only, bodies capped at 256 KiB, browser origins limited to settlens.com and claude.ai, and 60 requests per minute per IP address by default.
-
Request content not stored
Request content is processed in memory to compute the answer, then discarded; the rate-limit counters are kept in memory only. There is no access log: a call leaves a line, with its IP address, time and path, in the proxy's error log only in exceptional cases such as an error, a rate limit or an unusually large request.
-
Server content is data
Check messages, reasons and issues that can carry values chosen by the scanned server are reduced to one line of at most 300 characters. Returned payment terms are still the server's own values: agents must treat them as data, never as instructions.
Infrastructure
A small, static-first site with a short list of moving parts.
- Hosting
- A server rented from IONOS SE, in the European Union
- Transport
- HTTPS, with TLS terminated by the nginx reverse proxy in front of the application
- Application
- Static pages generated at build time, served by a Node.js server that also handles the pilot form, the token-protected scan API and the MCP endpoint
- Container
- Runs as the unprivileged node user with read-only code, a read-only root filesystem, all Linux capabilities dropped, no-new-privileges, memory, CPU and process limits, and npm removed; the port is bound to 127.0.0.1 behind the proxy
- Logs
- No access log. The proxy's error log records technical problems, such as requests that fail, hit a rate or size limit or are buffered to disk; the application logs only start-up, warning and error messages, capped at three files of 10 MB (see the privacy notice)
- Browser side
- No cookies, no analytics, no third-party scripts, fonts or embeds (see cookies)
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests; require-trusted-types-for 'script'; trusted-types 'none'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-site
Strict-Transport-Security: max-age=63072000
Supply chain
Few dependencies, all pinned, all checked on every change.
| Package | Version | Used for |
|---|---|---|
@noble/curves | 2.2.0 | secp256k1 recovery for EIP-712 signatures |
@noble/hashes | 2.2.0 | keccak-256 for EIP-712 hashing |
@x402/core | 2.28.0 | Official x402 V2 schema validation |
nodemailer | 10.1.1 | Runtime dependency |
proper-lockfile | 4.1.2 | Runtime dependency |
- Exact versions in
package.jsonand a committed lockfile, installed withnpm ci --ignore-scripts. - CI on Node.js 20, 22 and 24, with coverage thresholds of 85% lines, 60% branches and 90% functions.
npm auditat the high level and a CycloneDX SBOM on every CI run.- GitHub Actions pinned to full commit SHAs, Dependabot updates for npm and Actions weekly.
- Container base image pinned by sha256 digest; evidence signing uses
node:cryptoonly.
Responsible disclosure
Found a vulnerability in settlens.com, the MCP endpoint or the Settlens tools? Write to contact@settlens.com. Our security.txt lists the same contact.
-
Send a private report
Email contact@settlens.com. Do not open a public issue or post details publicly before a fix is available.
-
Include what we need to reproduce
The affected version, commit or URL; the smallest reproducible example; the impact and preconditions; whether real funds, keys or customer systems were involved; and how to reach you safely.
-
Leave secrets out
Never include private keys, bearer tokens, real PAYMENT-SIGNATURE values or unredacted customer data.
-
We coordinate the fix with you
We aim to acknowledge your report within two business days and to give an initial severity assessment within five, then keep you informed while we work on it and agree a disclosure date with you. These are operating targets, not contractual service levels.
Test safely
Test only deployments you own, or the local demo target. Use test networks and synthetic data. Denial of service, credential testing, settlement, transaction replay and fund movement are out of bounds.
Sources
Assess your endpoints under these rules
A pilot runs passive checks by default and the active probe only with your written authorization. You receive reports and a signed attestation you can verify offline.