If you discover a security vulnerability in the DMV, please report it responsibly.
Email: security@agentcommunity.org
Please include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
We'll acknowledge your report within 48 hours and work with you on a fix before any public disclosure.
- The web application at dmv.agentcommunity.org
- The Cloudflare Worker
dmv-agentcommunity(/api/register, the live certificate-verification route at/api/lookup,/api/card,/api/og,/badge/*,/c/:id/:name) - Supabase Edge Functions (live secret-gated registration and
lookup-agent, and badge) - The
@agentcommunity/dmv-agentnpm package - Certificate ID generation and verification logic
- Cloudflare Turnstile integration on the browser registration flow
@agentcommunity/dmv-agentis the one canonical capability;dmv-agentis compatibility-only, and alias source0.1.3must use the exact approved dependency range@agentcommunity/dmv-agent@^0.3.0.- The package verifier uses explicit archive allow-lists, exact license/docs
bytes, exact dependency/lifecycle/publish configuration, secret scans,
script-disabled clean installs, bounded registry requests, and SRI checks.
Production operations are opt-in via
--production-smoke; they never perform a registration or business-data write, but do consume quota and may populate caches. - npm publication is restricted to the main-only GitHub-hosted OIDC workflow,
canonical first. Candidate code never receives OIDC authority. Registry
signatures are not provenance; post-publish evidence separately requires
npm audit signaturescryptographic verification and exact SLSA source, workflow, ref, commit, builder, and artifact bindings. Trusted-publisher and protected-environment configuration remains an npm/GitHub owner action, and no long-lived npm release token belongs in this repository.
- Denial of service attacks
- Social engineering of project maintainers
- Issues in third-party dependencies (report those upstream)
- Zero secrets in client code — the Worker holds
TURNSTILE_SECRET_KEYandDMV_PROXY_SECRET; the Edge Functions holdDMV_PROXY_SECRETandSUPABASE_SERVICE_ROLE_KEY - Service role keys and the shared proxy secret are only in their server-side runtime environments, never in source
- Certificate IDs are content-addressed hashes rather than sequential values, which makes blind guessing harder. The lookup rate limit mitigates but does not eliminate enumeration risk.
- Anti-abuse on
/api/registeris owned by the Cloudflare Worker, not the Supabase edge function. Browser path: validate → Turnstile siteverify (server-side hostname +dmv_registeraction check) → shared CF rate limits (RL_OTP_EMAIL5/60s,RL_OTP_IP_EMAIL4/60s — bothnamespace_idvalues shared at the CF account level withagentCommunity_PAGE) → forward to Supabase. The live CLI/MCP path validatesmachine_fingerprint, applies the shared limits, then claims the exactREGISTER_FINGERPRINT_LIMITERSQLite Durable Object before upstream. One object per SHA-256 fingerprint hash transactionally caps the rolling budget at three. Only well-formed fresh 201 mints commit; only audited pre-INSERT 400/403/409 responses and exact 200 replays release. Every uncertain outcome stays pending for 600 seconds, then counts for 24 hours. The 600 seconds cover Supabase's documented 150-second request-idle timeout + 400-second Edge Function wall clock + a 50-second safety margin; the Worker's separate 45-second abort does not claim to cancel remote execution. Raw fingerprints and IPs never enter object storage. V3 is live as of 2026-08-02, and every recovery Worker must preserve v1/v2/v3 as forward-only production state. CAPTCHA always runs before shared counters so invalid tokens cannot exhaust quota for real users. Upstash Redis was removed from the Supabase edge function in the 2026-04-08 hardening pass. - The live public certificate verification boundary is
GET /api/lookup?id=CERT-IDon the Worker. It accepts certificate IDs, applies coarse/eventually consistentRL_CERT_LOOKUPat 60/60, then uses oneCERT_LOOKUP_LIMITERSQLite Durable Object per SHA-256 hashed IP for exact transactional 30/60 accounting and remaining/reset values. Responses produced before an authoritative Durable Object decision omit guessed remaining/reset telemetry. Durable Object failure fails closed before cache or upstream;BADGE_CACHE_KVstores results only. The Supabaselookup-agentfunction is an internal upstream with exact typed HTTP 200issued/not_foundenvelopes: it requires the Worker-setx-dmv-proxy: DMV_PROXY_SECRETvalue, compares it in constant time, fails closed when the secret is unset, and rejects direct callers before creating a Supabase client. Non-200 or malformed envelopes are unavailable and uncached. Domain lookup is unsupported. The boundary is live: mergedmainfabafe6(PR #20) is Worker versiond9755e66-3883-4970-be84-a59307011f14created2026-07-22T12:01:52.501Z. Production checks recorded200 issuedforREEF-068-BD0Q,200 not_foundforZZZZ-FFF-FFFD,400forINVALID, an exact 31st-call429, and secretless direct Edge403 direct_access_deprecated. The direct Edge URL is not a client API. - The Supabase edge function still runs validation, the lifetime cap, and the unique-cert-ID constraint as a defense-in-depth backstop.