Graphite is a transaction verification engine — security bugs in the verification path are critical.
Do NOT open a public issue for security vulnerabilities.
Instead, email: victorstanley13@gmail.com with:
- A clear description of the vulnerability
- The affected component (core engine, SAK integration, SDK, AI layer)
- Steps to reproduce or proof of concept
- Your assessment of severity (CRITICAL / HIGH / MEDIUM / LOW)
You will receive a response within 72 hours. If the vulnerability is confirmed, a fix will be prioritized and a security advisory will be published after the fix is released.
Graphite follows a fail-closed by default philosophy (Constitution P12):
- Unknown protocols are hard-capped at 0.55 confidence — no amount of caller-provided evidence can override this
- Unknown instructions on known protocols return
BLOCKED(confidence 0.0), not an error; novel instructions on known protocols surface a non-blocking warning (GAP-1) - NaN, Infinity, empty, and whitespace-only values in confidence signals and simulation baselines are rejected — they cannot bypass range checks or poison the trusted baseline accumulator
- The 8-layer pipeline can only reduce confidence or block — no layer can invent confidence that lower layers didn't earn
- AI/LLM output is advisory only (Constitution P1) — it never enters the verification path as a decision
The HTTP server defends against direct and replay-style abuse:
- Authentication — optional Bearer API key (
GRAPHITE_API_KEY), compared in constant time (SHA-256)./verifyand/manifestsrequire it when set;/healthstays open for load balancers. - Rate limiting — per-IP token bucket (
GRAPHITE_RATE_LIMIT, default 30 req/s), FIFO eviction, returns429on exhaustion. Protects the verification path from brute force and resource exhaustion. - CORS — denied by default;
GRAPHITE_CORS_ORIGINSenables specific browser origins only. Server-to-server clients are unaffected. - Audit log — append-only JSONL (
audit.jsonlunderGRAPHITE_DATA_DIR) recorded after every verification, covering all four outcomes: approved, blocked, HTTP 400, HTTP 500. Never logs request API keys or wallet private keys. - Graceful shutdown and trusted-proxy gating —
X-Forwarded-For(used for per-IP limiting) is honored only when the server is explicitly configured behind a trusted proxy.
The RPC client (active when GRAPHITE_RPC_URL is set) was live-audited against Helius mainnet + devnet:
- Retries with exponential backoff on
429/5xx;max_retrieshonored getAccountInfodistinguishesAccountNotFoundfrom a real zeroed account (no fabricated state)- Token freeze state is read from the correct byte offset (108)
- No credentials are logged; the API key is passed via request header/URL only
These are documented scope boundaries, not hidden vulnerabilities:
- No instruction data semantic parsing — Graphite matches known discriminators (hex byte comparison) but does not parse the semantic meaning of instruction data beyond the discriminator.
- L3 simulation is opt-in — L3 (Simulation Verification) runs live
simulateTransactionwhen an RPC client is attached (GRAPHITE_RPC_URL). Without an RPC client it reports an honestInconclusivestate, never a phantom pass. - AuditBind closes the verify-to-execute TOCTOU for the transfer path and any payload-bound instruction (
verifyInstructionre-hashes the exact instruction against the approvedcontent_hash, cross-language pinned-vector tested). Residual gap on the SAK swap path:methods.swaprebuilds the swap instruction internally, so a bound payload is not guaranteed to be the executed instruction —GRAPHITE_SWAP_STRICT=1requires a payload but does not force the executor to submit it. Full closure requires executing the bound instruction directly. SeeARCHITECTURE.md→ Known Boundary Limitations. - Caller-provided behavior evidence —
behavior_evidencefields are caller-supplied; the confidence engine deliberately zeroes the evidence-derived signals (Constitution G4) so this cannot inflate confidence.
See ROADMAP.md for the full Phase 2 plan.