Report privately via GitHub's security advisory form, or by email to deekhay7534@gmail.com.
Please do not open a public issue for anything in the first category below. The same private-first process applies if a scanner defect or other security failure may have produced an under-reported attestation. Include the affected asset and network, registry and transaction details when available, scanner version, and a reproduction or supporting evidence. Maintainers will coordinate mitigation and disclosure, notify known affected consumers, and publish a correction notice when it is safe to do so; see the attestation correction runbook.
There is no bug bounty. Assay is an early open-source project and cannot offer payment.
Assay is not a service holding user data, so the usual list does not map cleanly. What Assay produces is a claim about whether someone's money can be taken, and a contract that gates on that claim. The security-relevant failures are the ones that make a claim wrong in the dangerous direction.
docs/threat-model.md names the actors, what each can do, and every attack class that is already known — defended, accepted as a bounded risk, or out of scope, with the reason in each case. Read it before reporting: a gap listed there as accepted is still worth a report if you think the accepted reasoning is wrong, but it is not a discovery, and the answer will be the reasoning rather than a fix.
These are the bugs that matter most, because someone acts on the output.
- A scan reporting a severity lower than the issuer's flags justify.
- An asset whose issuer can confiscate (
auth_clawback_enabled) classifying belowhigh, orConfiscationMaskfailing to implyhigh. - Any path where attribution, reputation, age, or popularity lowers a severity. Severity is capability-only by design; a discount is a vulnerability, not a feature request. It would also create the obvious attack: buy attribution to get past a gate.
is_safereturningtruefor an asset that is unattested, stale, or above the caller's threshold — any failure to fail closed.- A forged or replayed attestation accepted by the registry.
- A parsing bug letting a stellar.toml claim an asset it does not issue, or letting a code-only match pass as reciprocal verification.
- Severity inflation that is systematic rather than incidental. A scanner that cries wolf gets ignored, and an ignored scanner protects nobody.
- Presenting a consumed third-party signal as an Assay conclusion, or dropping the attribution and source URL from evidence.
- Displaying a value that was never fetched, or rendering a failed fetch as a clean result. "We could not check" and "this is fine" must never look the same.
- Injection through issuer-controlled content — asset codes,
home_domain, stellar.toml fields, directory names — into the API response or the UI. Issuer-controlled strings are untrusted input. - Denial of service in the fetch layer: unbounded reads, missing timeouts, or a hostile domain able to stall a scan.
- An asset being a scam that Assay rates
clear. Assay measures issuer trap mechanics, not fraud in general. An asset with no authorization flags genuinely gives its issuer no special power, and Assay says so; the asset can still be worthless or an impersonation. This is documented in docs/severity-model.md and there is a subject in the eval set for exactly this case. - Accuracy of third-party data. StellarExpert's directory and blocklist are consumed and attributed, not curated by us. Report those upstream.
- An issuer changing its flags after a scan. Reports are point-in-time and carry
a timestamp; the contract exposes
attested_atso callers can set their own staleness policy. - Missing checks. A mechanic Assay does not examine yet is a feature request — open an issue.
The testnet registry's entire write path is the single assay-attester key.
Where it lives, how it is backed up, what an attacker holding it can and
cannot do, and the response to loss or compromise are documented in
docs/attester-key.md. A suspected key compromise that
produces under-reporting attestations counts as a critical report under the
policy above — report it privately first.
Pre-1.0. Fixes land on main; there are no maintained release branches. What
receives a fix depends on what you are reporting against.
| Version | Receives fixes | Notes |
|---|---|---|
main |
Yes | Builds from a checkout report their scanner version as devel (internal/version). |
Latest v* release tag |
Yes, by a new release | No release tag has been cut yet (CONTRIBUTING.md, "Releasing"). Once one exists, a fix ships as a new tag. |
Older v* tags |
No | Upgrade to the latest release. A report that reproduces only on an old tag is still welcome if it reached an attestation. |
Soroban contracts cannot be patched in place: the registry has no upgrade entrypoint, so a contract fix ships as a new deployment, recorded in docs/deployment.md, which is the source of truth for these addresses.
| Contract | Address | Receives fixes | Notes |
|---|---|---|---|
| Safety registry | CBK4FBIH… |
Yes, by redeployment | The live registry (wasm c4105b91…, source eec17a7). It predates revoke and TTL-on-write, which exist only in the source on main; see migrating. |
| Example gate | CAL5VYSW… |
Yes, by redeployment | The canonical gate (wasm ca40172e…). |
| Example gate (duplicate) | CCMA2SW2… |
Covered by CAL5VYSW… |
Identical wasm and policy; nothing refers to it. |
| Example gate (superseded) | CANO57JR… |
No, it cannot be | Known-flawed (#26). A gate pointing at it is in scope as an unfixed #26, see below. |
Contract source on main |
assay-contracts/ |
Yes | Includes code not yet deployed (revoke). Report against the source as well as against what runs. |
There is no pubnet deployment, so nothing on pubnet is supported.
Keeping this table current: update it in the same change as a release tag, a redeployment or a change of canonical instance. A report against an address missing from this table is answered from docs/deployment.md, not refused.
The assay-contracts registry and the example gate are deployed, on Stellar
testnet. There is no pubnet deployment. This is a live target: report against
what is running, not against what you assume is running.
docs/deployment.md is the source of truth for addresses, wasm hashes and deployment transactions. It is linked rather than copied here so there is one place to correct when the deployment changes.
Two things about that deployment are security-relevant:
- One gate instance is superseded and known-flawed.
CANO57JR…masks capability bits only, so it admits assets whose severity comes from reputation — the #26 failure. It cannot be removed, because Soroban contracts cannot be deleted, so it is still live.CAL5VYSW…is the canonical instance. A gate pointing atCANO57JR…is an unfixed #26 and is in scope as one. evidence_hashis independently verifiable. The encoding is specified in docs/contract-interface.md and was verified byte-for-byte against that procedure on 2026-09-17; docs/verifying.md walks the check.
Known limitations, documented rather than hidden, in docs/contract-interface.md: a single admin key can write any attestation, and nothing refreshes an attestation when an issuer's flags change. The full list, with the direction each one fails in, is docs/threat-model.md.