Threat model — what the enforcement layers refuse, and what they leave
Generated document. What the agent-time guards refuse, which requirements the tree does not reach, and the limits the covered rows state about themselves. Every figure below is derived from
tools/conformance-map.jsonbytools/gen-conformance-docs.mjs; a hand edit here is a claim nobody reviewed and reds thedocs-syncstep.
What this document does not claim
Section titled “What this document does not claim”A mapping is not a verification, and this document claims no level. A verification level attaches to a verification of an application performed by an assessor against that application; a template cannot hold one and a generator cannot confer one. This map states which live control in the tree bears on each requirement, how much of it that control reaches, and what is left — so an assessor starts from an honest ledger and a consumer never mistakes a template for a verification. It never says the generated application is ASVS Level 1, 2 or 3, MASVS-verified, or CRA-conformant, and tools/check-conformance-map.mjs reds any sentence in the register that does.
The CRA rows carry a shelf life. CRA conformity is a manufacturer’s legal act — Annex I obligations, a conformity assessment, a declaration, CE marking — that no code tree performs, and no harmonised standard for the CRA had been cited in the Official Journal as of 2026-08-16 — the register records: “none cited in the Official Journal as of the verified date; ETSI’s CRA ENs were in approval — re-verify per the calendar row conformance-cra-hens-citation”. The Annex I rows are mapped against the regulation’s text directly and must be re-read when a harmonised standard is cited.
Module rows are conditional. 8 row(s) rest on an opt-in module (module set in the register) and are graded on the assumption that the module is enabled; on a tree without it the row is CONDITIONAL, judged for liveness only where the module’s docs/modules/<name>/README.md marker exists, and its control may not run here at all.
Organisation-boundary rows are enumerated, never graded up. 39 row(s) name something only the operating organisation can meet (policies, processes, notifications, contracts); the register may not grade them covered or partial, and this document lists them so nobody mistakes the tree’s silence for the operator’s compliance.
Grades are conservative by rule. Absence of a surface is never coverage; where two grades are defensible the lower is taken; covered may not rest on documentation alone; and not-covered is not a failure the gate reds on — it is the honest statement of what would be needed.
How to read this
Section titled “How to read this”Three layers enforce this tree: agent-time hooks (the rule tables below refuse a write or a command at the moment it is attempted), the validate/Stop chains (docs/harness/gates-catalog.md), and CI lanes. This document is the hooks’ half plus the map’s negative space: every rule the guards run, grouped by the table that holds it; every requirement the map grades not-covered; every module-conditional row; and the residual each covered row states in its own words. The positive half — which control bears on which requirement — is docs/compliance/controls-crosswalk.md.
Agent-time refusals
Section titled “Agent-time refusals”Rule tables from .claude/hooks/lib/guard-rules.mjs, in source order. Each rule is denied on the FIRST match; every id has a behavioural canary in the hook-contract suite. A rule that a conformance row rests on says so.
BASH_RULES (pretool-bash-guard.mjs)
Section titled “BASH_RULES (pretool-bash-guard.mjs)”rm-rf— Blocked: a recursive force-delete (any flag spelling, any shell —rm,Remove-Item,del,rd) is forbidden by the harness.shell-write-protected— Blocked: shell writes to the enforcement surface (gate scripts, hooks, stamps, lockfiles, migrations, workflows, the strictness configs, the generated native dirs) bypass the write-guard — edit via the Write tool with HARNESS_ALLOW_SELF_EDIT=1 (human-in-the-loop).interpreter-write-protected— Blocked: an inline interpreter (node -e,python -c,deno eval, dd/base64) writing to the enforcement surface bypasses the write-guard the same way a redirect would — widening an escape list (tools/rls-exempt.json), doctoring a gate script, or forging a stamp is a human-in-the-loop act (HARNESS_ALLOW_SELF_EDIT=1).gen-lock-writer— Blocked: regenerating a hash lock is how an edit to the locked files becomes invisible — the lock is a hash OF the thing being checked, not a derivation from something else the gates judge.chmod-protected— Blocked: chmod on the enforcement surface.rm-protected— Blocked: deleting a file on the enforcement surface (gate scripts, hooks, stamps, lockfiles, migrations, workflows, the strictness configs).truncate-protected— Blocked: truncating a file on the enforcement surface.move-protected-away— Blocked: moving a file OFF the enforcement surface leaves nothing behind to check — the same outcome as deleting it, spelled as a rename.git-restore-old-revision— Blocked: checking out an OLDER REVISION of a protected file reinstates a gate script from before a rule existed, or a floor from before a step existed, with a clean working tree afterwards.self-rebaseline-writer— Blocked: re-recording a ratchet BASELINE (the surviving-mutant set, the gzip floor) accepts the regression the ratchet just caught, and leaves every gate green by construction.apply-proposal-invocation— Blocked:apply-proposalwrites a staged register edit into place, and applying it is the decision the write guard reserves for a human.git-hookspath-repoint— Blocked: repointing core.hooksPath disables the lefthook commit-time layer.dev-auth-access— Blocked: .dev-auth/ holds local signing material — it is never read, copied, or listed from shell.git-force-push— Blocked: force-push is forbidden;git-reset-hard— Blocked: 'git reset --hard' destroys uncommitted work.git-commit-no-verify— Blocked: bypassing commit hooks (--no-verify) defeats the gate;git-push-no-verify— Blocked: bypassing the pre-push hooks (--no-verify) skips the typecheck, lint and dead-code jobs;lefthook-skip-env— Blocked: LEFTHOOK=0, LEFTHOOK_EXCLUDE, LEFTHOOK_BIN and LEFTHOOK_CONFIG each skip or replace the lefthook commit-time layer;fork-bomb— Blocked: fork bomb pattern.read-env-file— Blocked: reading .env files is forbidden; — bears on 13.3.2 (partial)source-env-file— Blocked: sourcing .env files is forbidden;credential-file-read— Blocked: app-signing/credential material (*.keystore, *.jks, *.p8, *.p12, google-services.json, GoogleService-Info.plist) is never read, copied, or echoed from shell — credentials live only in the EAS/CI secret store.expo-token-leak— Blocked: EXPO_TOKEN must never be set, echoed, or read into shell output — CI injects it from secrets.eas-credentials— Blocked:eas credentialsmanages app-signing material — a human-only surface.expo-prebuild— Blocked:expo prebuildregenerates the native dirs by hand — the generated android/ and ios/ trees are never local artifacts.git-add-native-dirs— Blocked: the generated native dirs (android/, ios/) are never committed — native surface changes go through app.config.ts + reviewed config plugins, and CI regenerates the dirs from a clean tree.knip-fix— Blocked:knip --fixauto-deletes code and has false positives;dependency-update— Blocked: bulk dependency updates are Renovate-owned (pinned, cooled-down, reviewed).destructive-sql— Blocked: destructive SQL must go through a reviewed, ADR-coupled migration.
MCP_RULES (pretool-mcp-guard.mjs)
Section titled “MCP_RULES (pretool-mcp-guard.mjs)”mcp-write-on-readonly— this server is registered readOnly in tools/approved-tools.json, and the tool name is write-shaped.
WRITE_PROTECTED (pretool-write-guard.mjs)
Section titled “WRITE_PROTECTED (pretool-write-guard.mjs)”harness-config— protected path^tools\/harness\.config\.mjs$validate-runner— protected path^tools\/validate\.mjs$validate-floor— protected path^tools\/validate\.floor\.json$gate-scripts— protected path^tools\/(check-[^/]+|build-check|perf-baseline)\.mjs$citation-domains— protected path^tools\/lib\/citation-domains\.mjs$tools-lib— protected path^tools\/lib\/tools-mcp— protected path^tools\/mcp\/lock-json— protected path^tools\/(identity|prompts)\.lock\.json$rls-exempt— protected path^tools\/rls-exempt\.json$tenancy-contract— protected path^tools\/tenancy\.json$security-definer-allow— protected path^tools\/security-definer-allow\.json$audit-columns— protected path^tools\/audit-columns\.json$pii-columns— protected path^tools\/pii-columns\.json$db-limits— protected path^tools\/db-limits\.json$— bears on 2.1.3 (partial), 2.3.2 (partial), 2.3.4 (partial), 4.3.1 (partial), 15.4.2 (partial), 15.4.3 (partial), 15.4.4 (partial)data-flow— protected path^tools\/data-flow\.json$— bears on 14.1.1 (partial), 14.2.7 (partial), MASVS-PRIVACY-4 (partial), CRA-I.2.m (partial)observability-sinks— protected path^tools\/observability\.json$suppressions-allow— protected path^tools\/suppressions-allow\.json$resilience-register— protected path^tools\/resilience\.json$auth-tunables— protected path^tools\/auth-tunables\.json$store-tunables— protected path^tools\/store-tunables\.json$reviewer-triggers— protected path^tools\/reviewer-triggers\.json$rate-limit-budget— protected path^tools\/rate-limit-budget\.json$security-headers-policy— protected path^tools\/security-headers\.json$essential-eight-register— protected path^tools\/essential-eight\.json$conformance-map-register— protected path^tools\/conformance-map\.json$migrations-allow— protected path^tools\/migrations-allow\.json$grant-bound-allow— protected path^tools\/grant-bound-allow\.json$framework-floor— protected path^tools\/framework-floor\.json$cc-floor— protected path^tools\/cc-floor\.json$db-perf-baseline— protected path^tools\/db-perf-baseline\.json$query-shapes-manifest— protected path^tools\/generated\/query-shapes\.json$action-inventory-manifest— protected path^tools\/generated\/action-inventory\.json$event-catalog-manifest— protected path^tools\/generated\/event-catalog\.json$claude-rules— protected path^\.claude\/rules\/claude-agents— protected path^\.claude\/agents\/claude-commands— protected path^\.claude\/commands\/claude-skills— protected path^\.claude\/skills\/agents-lock— protected path^tools\/agents\.lock\.json$provenance-overrides— protected path^tools\/provenance-overrides\.json$decision-groups— protected path^tools\/decision-groups\.json$license-exceptions— protected path^tools\/license-exceptions\.json$eol-register— protected path^tools\/eol\.json$support-register— protected path^tools\/support-register\.json$surfaces-register— protected path^tools\/surfaces\.json$backup-posture— protected path^tools\/backup-posture\.json$expo-permissions— protected path^tools\/expo-permissions\.json$expo-plugins— protected path^tools\/expo-plugins\.json$store-policy— protected path^tools\/store-policy\.json$modules-register— protected path^tools\/modules\.json$exports-walls-census— harness-owned census: tools/exports-walls.json is hash-pinned by gate-integrity, and an owned file is not a register a proposal can change, so an agent never edits it.bundle-budget— protected path^tools\/bundle-budget\.json$perf-baseline— protected path^tools\/perf-baseline\.json$perf-budget— protected path^tools\/perf-budget\.json$interaction-budget— protected path^tools\/interaction-budget\.json$startup-budget— protected path^tools\/startup-budget\.json$styleguide-manifest— protected path^tools\/styleguide\.manifest\.json$mutation-baseline— protected path^tools\/mutation-baseline\.json$mutation-scope-extra— protected path^tools\/mutation-scope-extra\.json$route-allowlist— protected path^tools\/route-allowlist\.json$web-route-allowlist— protected path^tools\/web-route-allowlist\.json$dto-bounds-allow— protected path^tools\/dto-bounds-allow\.json$duplication-allow— protected path^tools\/duplication-allow\.json$vertical-anatomy-allow— protected path^tools\/vertical-anatomy-allow\.json$field-notes— protected path^tools\/field-notes\.json$i18n-allow— protected path^tools\/i18n-allow\.json$test-quality-allow— protected path^tools\/test-quality-allow\.json$rls-runner— protected path^tests\/rls\/run-rls\.mjs$lefthook— protected path^lefthook\.yml$lefthook-local— protected path^(?:\.config\/|\.)?lefthook-local\.(?:ya?ml|jsonc?|toml)$git-hooks-dir— protected path^\.git\/hooks\/git-config— protected path^\.git\/config$github-workflows— protected path^\.github\/workflows\/codeowners— protected path^\.github\/CODEOWNERS$actionlint-config— protected path^\.github\/actionlint\.yaml$zizmor-config— protected path^\.github\/zizmor\.yml$pr-template— protected path^\.github\/pull_request_template\.md$gitignore— protected path^\.gitignore$renovate-config— protected path^renovate\.json$stryker-config— protected path^stryker\.config\.mjs$commitlint-config— protected path^commitlint\.config\.mjs$tools-ci— protected path^tools\/ci\/claude-hooks— protected path^\.claude\/hooks\/claude-statusline— protected path^\.claude\/statusline\.mjs$approved-tools— protected path^tools\/approved-tools\.json$secret-patterns— protected path^tools\/secret-patterns\.json$doctrine-symbols— protected path^tools\/doctrine-symbols\.json$stop-floor— protected path^tools\/stop\.floor\.json$retrofit-accept— protected path^tools\/retrofit-accept\.json$secret-scan-allow— protected path^tools\/secret-scan-allow\.json$eslint-config— protected path^eslint\.config\.mjs$biome-config— protected path^biome\.jsonc$knip-config— protected path^knip\.json$dependency-cruiser— protected path^\.dependency-cruiser\.cjs$vitest-config— protected path^vitest\.config\.ts$jest-config— protected path^apps\/mobile\/jest\.config\.js$tsconfig— protected path^tsconfig(\.base)?\.json$pnpm-workspace— protected path^pnpm-workspace\.yaml$gitleaks-config— protected path^\.gitleaks\.toml$claude-settings— protected path^\.claude\/settings\.json$claude-settings-local— protected path^\.claude\/settings\.local\.json$mcp-json— protected path^\.mcp\.json$harness-dir— protected path^\.harness\/cng-android— protected path^apps\/mobile\/android\/cng-ios— protected path^apps\/mobile\/ios\/
WRITE_CONFIG_CHECKS (pretool-write-guard.mjs)
Section titled “WRITE_CONFIG_CHECKS (pretool-write-guard.mjs)”package-lifecycle-script— npm lifecycle scripts (preinstall/install/postinstall/prepublish/prepack/prepare) execute on everypnpm install— in CI, on every machine, BEFORE any gate in this repo runs.
WRITE_GLOBAL_CHECKS (pretool-write-guard.mjs)
Section titled “WRITE_GLOBAL_CHECKS (pretool-write-guard.mjs)”dangerously-set-inner-html— dangerouslySetInnerHTML is banned (XSS); — bears on 1.1.2 (partial), 1.2.1 (partial), 3.2.2 (partial)expo-public-secret-name— EXPO_PUBLIC_-prefixed vars are inlined into the shipped client bundle — never put secret-shaped names there.next-public-secret-name— NEXT_PUBLIC_-prefixed vars are inlined into the shipped web bundle — never put secret-shaped names there.weak-crypto-algorithm— That algorithm has no defensible use in new code: ECB leaks plaintext structure, createCipher() derives a key with a static IV, and MD5/SHA-1/DES/RC4 are broken. — bears on 11.2.3 (partial), 11.3.1 (partial), 11.4.1 (partial), 11.4.3 (partial), MASVS-CRYPTO-1 (partial)hardcoded-key-material— That is a 256-bit key literal in source. — bears on MASVS-CRYPTO-2 (partial)math-random-key-material— A key, IV, nonce or salt derived from Math.random is not one — Math.random is not a CSPRNG on any engine.set-config-session-wide— set_config(..., false) sets the GUC session-wide and LEAKS across pooled connections — the third argument must be true (transaction-local).set-session-app-guc— RLS identity GUCs must be SET LOCAL inside a transaction, never session-wide (pooling leak).pg-session-timeout-set— SET statement_timeout / lock_timeout / idle_in_transaction_session_timeout without LOCAL changes the SESSION, and a pooled session is handed to the NEXT tenant's request with your ceiling still on it.pg-advisory-session-lock— pg_advisory_lock is SESSION-scoped: on a pooled connection it survives the request that took it, so an error path leaks a lock that blocks every later caller of that key and no pool release can clear.pg-prepared-statement— a postgres() connection with prepared statements left on breaks under Supavisor transaction mode: the backend that holds the prepared statement is not the backend the next request gets, and the driver sends the cached NAME — an intermittent 26000 that no local test against a direct connection reproduces.vitest-workspace-file— vitest workspace files are banned — projects are defined in the root vitest.config.ts (single gate surface).
WRITE_SQL_CHECKS (pretool-write-guard.mjs)
Section titled “WRITE_SQL_CHECKS (pretool-write-guard.mjs)”rls-disable-or-noforce— turning RLS off is not a schema change, it is the removal of this codebase's only authorization boundary — every table keeps ENABLE + FORCE ROW LEVEL SECURITY.policy-to-public-role— a policy granted TO public or TO anon applies to unauthenticated callers — policies are TO authenticated, and anon holds no grants at all.policy-using-true— USING (true) / WITH CHECK (true) is a policy that permits every row — RLS is enabled and enforcing nothing.security-definer-no-search-path— SECURITY DEFINER withoutSET search_path = ''is the standard privilege-escalation footgun: the caller controls name resolution and your function runs as its owner.
Uncovered and residual
Section titled “Uncovered and residual”Every row the map grades not-covered — nothing in the tree bears on it: honestly unbuilt, or the consumer’s to build. 105 row(s). The register’s note on each says what would be needed.
ASVS 5.0.0 (94)
Section titled “ASVS 5.0.0 (94)”- 1.1.1 — Verify that input is decoded or unescaped into a canonical form only once, it is only decoded when encoded data in that form is expected, and that this is done before processing the input further, for example it is not performed after input validation or sanitization.
- 1.2.2 — Verify that when dynamically building URLs, untrusted data is encoded according to its context (e.g., URL encoding or base64url encoding for query or path parameters).
- 1.2.3 — Verify that output encoding or escaping is used when dynamically building JavaScript content (including JSON), to avoid changing the message or document structure (to avoid JavaScript and JSON injection).
- 1.2.9 — Verify that the application escapes special characters in regular expressions (typically using a backslash) to prevent them from being misinterpreted as metacharacters.
- 1.3.12 — Verify that regular expressions are free from elements causing exponential backtracking, and ensure untrusted input is sanitized to mitigate ReDoS or Runaway Regex attacks.
- 1.5.2 — Verify that deserialization of untrusted data enforces safe input handling, such as using an allowlist of object types or restricting client-defined object types, to prevent deserialization attacks.
- 1.5.3 — Verify that different parsers used in the application for the same data type (e.g., JSON parsers, XML parsers, URL parsers), perform parsing in a consistent way and use the same character encoding mechanism to avoid issues such as JSON Interoperability vulnerabilities or different URI or file parsing behavior being exploited in Remote File Inclusion (RFI) or Server-side Request Forgery (SSRF) attacks.
- 2.1.2 — Verify that the application's documentation defines how to validate the logical and contextual consistency of combined data items, such as checking that suburb and ZIP code match.
- 2.2.3 — Verify that the application ensures that combinations of related data items are reasonable according to the pre-defined rules.
- 2.3.1 — Verify that the application will only process business logic flows for the same user in the expected sequential step order and without skipping steps.
- 2.3.3 — Verify that transactions are being used at the business logic level such that either a business logic operation succeeds in its entirety or it is rolled back to the previous correct state.
- 2.3.5 — Verify that high-value business logic flows require multi-user approval to prevent unauthorized or accidental actions.
- 2.4.2 — Verify that business logic flows require realistic human timing, preventing excessively rapid transaction submissions.
- 3.1.1 — Verify that application documentation states the expected security features that browsers using the application must support (such as HTTPS, HTTP Strict Transport Security (HSTS), Content Security Policy (CSP), and other relevant HTTP security mechanisms).
- 3.2.3 — Verify that the application avoids DOM clobbering when using client-side JavaScript by employing explicit variable declarations, performing strict type checking, avoiding storing global variables on the document object, and implementing namespace isolation.
- 3.3.3 — Verify that cookies have the '__Host-' prefix for the cookie name unless they are explicitly designed to be shared with other hosts.
- 3.3.4 — Verify that if the value of a cookie is not meant to be accessible to client-side scripts (such as a session token), the cookie must have the 'HttpOnly' attribute set and the same value (e.
- 3.4.2 — Verify that the Cross-Origin Resource Sharing (CORS) Access-Control-Allow-Origin header field is a fixed value by the application, or if the Origin HTTP request header field value is used, it is validated against an allowlist of trusted origins.
- 3.7.5 — Verify that the application behaves as documented (such as warning the user or blocking access) if the browser used to access the application does not support the expected security features.
- 4.1.2 — Verify that only user-facing endpoints (intended for manual web-browser access) automatically redirect from HTTP to HTTPS, while other services or endpoints do not implement transparent redirects.
- 4.1.3 — Verify that any HTTP header field used by the application and set by an intermediary layer, such as a load balancer, a web proxy, or a backend-for-frontend service, cannot be overridden by the end-user.
- 4.1.4 — Verify that only HTTP methods that are explicitly supported by the application or its API (including OPTIONS during preflight requests) can be used and that unused methods are blocked.
- 4.3.2 — Verify that GraphQL introspection queries are disabled in the production environment unless the GraphQL API is meant to be used by other parties.
- 6.1.2 — Verify that a list of context-specific words is documented in order to prevent their use in passwords.
- 6.2.1 — Verify that user set passwords are at least 8 characters in length although a minimum of 15 characters is strongly recommended.
- 6.2.2 — Verify that users can change their password.
- 6.2.3 — Verify that password change functionality requires the user's current and new password.
- 6.2.4 — Verify that passwords submitted during account registration or password change are checked against an available set of, at least, the top 3000 passwords which match the application's password policy, e.g.
- 6.2.6 — Verify that password input fields use type=password to mask the entry.
- 6.2.7 — Verify that "paste" functionality, browser password helpers, and external password managers are permitted.
- 6.2.8 — Verify that the application verifies the user's password exactly as received from the user, without any modifications such as truncation or case transformation.
- 6.2.9 — Verify that passwords of at least 64 characters are permitted.
- 6.2.11 — Verify that the documented list of context specific words is used to prevent easy to guess passwords being created.
- 6.2.12 — Verify that passwords submitted during account registration or password changes are checked against a set of breached passwords.
- 6.3.5 — Verify that users are notified of suspicious authentication attempts (successful or unsuccessful).
- 6.3.6 — Verify that email is not used as either a single-factor or multi-factor authentication mechanism.
- 6.4.3 — Verify that a secure process for resetting a forgotten password is implemented, that does not bypass any enabled multi-factor authentication mechanisms.
- 6.4.6 — Verify that administrative users can initiate the password reset process for the user, but that this does not allow them to change or choose the user's password.
- 6.5.1 — Verify that lookup secrets, out-of-band authentication requests or codes, and time-based one-time passwords (TOTPs) are only successfully usable once.
- 6.5.5 — Verify that out-of-band authentication requests, codes, or tokens, as well as time-based one-time passwords (TOTPs) have a defined lifetime.
- 6.5.8 — Verify that time-based one-time passwords (TOTPs) are checked based on a time source from a trusted service and not from an untrusted or client provided time.
- 7.1.1 — Verify that the user's session inactivity timeout and absolute maximum session lifetime are documented, are appropriate in combination with other controls, and that the documentation includes justification for any deviations from NIST SP 800-63B re-authentication requirements.
- 7.1.2 — Verify that the documentation defines how many concurrent (parallel) sessions are allowed for one account as well as the intended behaviors and actions to be taken when the maximum number of active sessions is reached.
- 7.2.3 — Verify that if reference tokens are used to represent user sessions, they are unique and generated using a cryptographically secure pseudo-random number generator (CSPRNG) and possess at least 128 bits of entropy.
- 7.3.1 — Verify that there is an inactivity timeout such that re-authentication is enforced according to risk analysis and documented security decisions.
- 7.3.2 — Verify that there is an absolute maximum session lifetime such that re-authentication is enforced according to risk analysis and documented security decisions.
- 7.4.3 — Verify that the application gives the option to terminate all other active sessions after a successful change or removal of any authentication factor (including password change via reset or recovery and, if present, an MFA settings update).
- 7.4.5 — Verify that application administrators are able to terminate active sessions for an individual user or for all users.
- 7.5.1 — Verify that the application requires full re-authentication before allowing modifications to sensitive account attributes which may affect authentication such as email address, phone number, MFA configuration, or other information used in account recovery.
- 7.5.2 — Verify that users are able to view and (having authenticated again with at least one factor) terminate any or all currently active sessions.
- 8.1.2 — Verify that authorization documentation defines rules for field-level access restrictions (both read and write) based on consumer permissions and resource attributes.
- 8.1.4 — Verify that authentication and authorization documentation defines how environmental and contextual factors are used in decision-making, in addition to function-level, data-specific, and field-level authorization.
- 8.2.3 — Verify that the application ensures that field-level access is restricted to consumers with explicit permissions to specific fields to mitigate broken object property level authorization (BOPLA).
- 8.2.4 — Verify that adaptive security controls based on a consumer's environmental and contextual attributes (such as time of day, location, IP address, or device) are implemented for authentication and authorization decisions, as defined in the application's documentation.
- 9.2.3 — Verify that the service only accepts tokens which are intended for use with that service (audience).
- 10.1.2 — Verify that the client only accepts values from the authorization server (such as the authorization code or ID Token) if these values result from an authorization flow that was initiated by the same user agent session and transaction.
- 10.2.1 — Verify that, if the code flow is used, the OAuth client has protection against browser-based request forgery attacks, commonly known as cross-site request forgery (CSRF), which trigger token requests, either by using proof key for code exchange (PKCE) functionality or checking the 'state' parameter that was sent in the authorization request.
- 10.3.1 — Verify that the resource server only accepts access tokens that are intended for use with that service (audience).
- 10.3.5 — Verify that the resource server prevents the use of stolen access tokens or replay of access tokens (from unauthorized parties) by requiring sender-constrained access tokens, either Mutual TLS for OAuth 2 or OAuth 2 Demonstration of Proof of Possession (DPoP).
- 10.4.4 — Verify that for a given client, the authorization server only allows the usage of grants that this client needs to use.
- 10.4.8 — Verify that refresh tokens have an absolute expiration, including if sliding refresh token expiration is applied.
- 10.4.9 — Verify that refresh tokens and reference access tokens can be revoked by an authorized user using the authorization server user interface, to mitigate the risk of malicious clients or stolen tokens.
- 11.1.1 — Verify that there is a documented policy for management of cryptographic keys and a cryptographic key lifecycle that follows a key management standard such as NIST SP 800-57.
- 11.1.2 — Verify that a cryptographic inventory is performed, maintained, regularly updated, and includes all cryptographic keys, algorithms, and certificates used by the application.
- 11.1.4 — Verify that a cryptographic inventory is maintained.
- 11.2.4 — Verify that all cryptographic operations are constant-time, with no 'short-circuit' operations in comparisons, calculations, or returns, to avoid leaking information.
- 11.4.2 — Verify that passwords are stored using an approved, computationally intensive, key derivation function (also known as a "password hashing function"), with parameter settings configured based on current guidance.
- 11.5.2 — Verify that the random number generation mechanism in use is designed to work securely, even under heavy demand.
- 11.6.1 — Verify that only approved cryptographic algorithms and modes of operation are used for key generation and seeding, and digital signature generation and verification.
- 12.3.2 — Verify that TLS clients validate certificates received before communicating with a TLS server.
- 13.1.2 — Verify that for each service the application uses, the documentation defines the maximum number of concurrent connections (e.g., connection pool limits) and how the application behaves when that limit is reached, including any fallback or recovery mechanisms, to prevent denial of service conditions.
- 13.1.4 — Verify that the application's documentation defines the secrets that are critical for the security of the application and a schedule for rotating them, based on the organization's threat model and business requirements.
- 13.2.3 — Verify that if a credential has to be used for service authentication, the credential being used by the consumer is not a default credential (e.g., root/root or admin/admin).
- 13.2.5 — Verify that the web or application server is configured with an allowlist of resources or systems to which the server can send requests or load data or files from.
- 13.3.3 — Verify that all cryptographic operations are performed using an isolated security module (such as a vault or hardware security module) to securely manage and protect key material from exposure outside of the security module.
- 13.3.4 — Verify that secrets are configured to expire and be rotated based on the application's documentation.
- 13.4.2 — Verify that debug modes are disabled for all components in production environments to prevent exposure of debugging features and information leakage.
- 13.4.7 — Verify that the web tier is configured to only serve files with specific file extensions to prevent unintentional information, configuration, and source code leakage.
- 14.1.2 — Verify that all sensitive data protection levels have a documented set of protection requirements.
- 14.2.6 — Verify that the application only returns the minimum required sensitive data for the application's functionality.
- 14.3.1 — Verify that authenticated data is cleared from client storage, such as the browser DOM, after the client or session is terminated.
- 15.1.5 — Verify that application documentation highlights parts of the application where "dangerous functionality" is being used.
- 15.2.4 — Verify that third-party components and all of their transitive dependencies are included from the expected repository, whether internally owned or an external source, and that there is no risk of a dependency confusion attack.
- 15.2.5 — Verify that the application implements additional protections around parts of the application which are documented as containing "dangerous functionality" or using third-party libraries considered to be "risky components".
- 15.3.2 — Verify that where the application backend makes calls to external URLs, it is configured to not follow redirects unless it is intended functionality.
- 15.3.4 — Verify that all proxying and middleware components transfer the user's original IP address correctly using trusted data fields that cannot be manipulated by the end user, and the application and web server use this correct value for logging and security decisions such as rate limiting, taking into account that even the original IP address may not be reliable due to dynamic IPs, VPNs, or corporate firewalls.
- 15.3.6 — Verify that JavaScript code is written in a way that prevents prototype pollution, for example, by using Set() or Map() instead of object literals.
- 15.3.7 — Verify that the application has defenses against HTTP parameter pollution attacks, particularly if the application framework makes no distinction about the source of request parameters (query string, body parameters, cookies, or header fields).
- 16.1.1 — Verify that an inventory exists documenting the logging performed at each layer of the application's technology stack, what events are being logged, log formats, where that logging is stored, how it is used, how access to it is controlled, and for how long logs are kept.
- 16.2.2 — Verify that time sources for all logging components are synchronized, and that timestamps in security event metadata use UTC or include an explicit time zone offset.
- 16.3.2 — Verify that failed authorization attempts are logged.
- 16.3.3 — Verify that the application logs the security events that are defined in the documentation and also logs attempts to bypass the security controls, such as input validation, business logic, and anti-automation.
- 16.3.4 — Verify that the application logs unexpected errors and security control failures such as backend TLS failures.
- 16.5.4 — Verify that a "last resort" error handler is defined which will catch all unhandled exceptions.
MASVS 2.1 (8)
Section titled “MASVS 2.1 (8)”- MASVS-CODE-1 — The app requires an up-to-date platform version.
- MASVS-NETWORK-2 — The app performs identity pinning for all remote endpoints under the developer's control.
- MASVS-PLATFORM-3 — The app uses the user interface securely.
- MASVS-PRIVACY-2 — The app prevents identification of the user.
- MASVS-RESILIENCE-1 — The app validates the integrity of the platform.
- MASVS-RESILIENCE-2 — The app implements anti-tampering mechanisms.
- MASVS-RESILIENCE-3 — The app implements anti-static analysis mechanisms.
- MASVS-RESILIENCE-4 — The app implements anti-dynamic analysis techniques.
CRA Annex I (3)
Section titled “CRA Annex I (3)”- CRA-I.2 — On the basis of the cybersecurity risk assessment referred to in Article 13(2) and where applicable, products with digital elements shall:
- CRA-II.4 — once a security update has been made available, share and publicly disclose information about fixed vulnerabilities, including a description of the vulnerabilities, information allowing users to identify the product with digital elements affected, the impacts of the vulnerabilities, their severity and clear and accessible information helping users to remediate the vulnerabilities;
- CRA-II.8 — ensure that, where security updates are available to address identified security issues, they are disseminated without delay and, unless otherwise agreed between a manufacturer and a business user in relation to a tailor-made product with digital elements, free of charge, accompanied by advisory messages providing users with the relevant information, including on potential action to be taken.
Module-conditional rows
Section titled “Module-conditional rows”Graded on the assumption the module is enabled; without it, the row is conditional and its control may not run here.
- 11.2.2 (ASVS 5.0.0, partial, module
e2ee) — Verify that the application is designed with crypto agility such that random number, authenticated encryption, MAC, or hashing algorithms, key lengths, rounds, ciphers and modes can be reconfigured, upgraded, or swapped at any time, to protect against cryptographic breaks. - 11.2.5 (ASVS 5.0.0, partial, module
e2ee) — Verify that all cryptographic modules fail securely, and errors are handled in a way that does not enable vulnerabilities, such as Padding Oracle attacks. - 11.3.2 (ASVS 5.0.0, partial, module
e2ee) — Verify that only approved ciphers and modes such as AES with GCM are used. - 11.3.3 (ASVS 5.0.0, partial, module
e2ee) — Verify that encrypted data is protected against unauthorized modification preferably by using an approved authenticated encryption method or by combining an approved encryption method with an approved MAC algorithm. - 11.3.4 (ASVS 5.0.0, partial, module
e2ee) — Verify that nonces, initialization vectors, and other single-use numbers are not used for more than one encryption key and data-element pair. - 11.6.2 (ASVS 5.0.0, partial, module
e2ee) — Verify that approved cryptographic algorithms are used for key exchange (such as Diffie-Hellman) with a focus on ensuring that key exchange mechanisms use secure parameters. - CRA-I.2.c (CRA Annex I, partial, module
eas-update) — ensure that vulnerabilities can be addressed through security updates, including, where applicable, through automatic security updates that are installed within an appropriate timeframe enabled as a default setting, with a clear and easy-to-use opt-out mechanism, through the notification of available updates to users, and the option to temporarily postpone them; - CRA-I.2.e (CRA Annex I, partial, module
e2ee) — protect the confidentiality of stored, transmitted or otherwise processed data, personal or other, such as by encrypting relevant data at rest or in transit by state of the art mechanisms, and by using other technical means;
Stated limits
Section titled “Stated limits”What each covered row says it does NOT reach, in the register’s own words — extracted from the note at its residual marker. A covered row without a stated limit is omitted here, not paraphrased.
- 3.4.1 (ASVS 5.0.0,
security-headers) — Honest limit, stated by the gate itself: neither can prove the PRODUCTION response — a header-stripping CDN in front of a correct config is invisible from here. The seeded delete-account Edge Function answers on Supabase's own hostname, where HSTS is the platform's header, not this config's. Preload-list membership is 3.7.4's row, not this one. - 3.4.5 (ASVS 5.0.0,
security-headers) — Residual: per-element referrerpolicy attributes are not governed, and an internal-only deployment wanting to suppress even the hostname (no-referrer) would relax nothing by accident — tools/security-headers.json is write-guard-protected (guard rule security-headers-policy), listed in gate-integrity's ESCAPE_LISTS so an edit must be committed rather than left dirty at gate time, and under CODEOWNERS — so the change lands as a reviewed diff. - 3.4.8 (ASVS 5.0.0,
security-headers) — Residual: the standing CDN caveat — the gate proves the config, the lane proves its build, neither proves production. - 3.5.8 (ASVS 5.0.0,
security-headers) — Residual: CORP governs no-cors embedding only in browsers that honour it; a consumer who intentionally serves embeddable cross-origin resources must relax tools/security-headers.json — write-guard-protected and commit-enforced by gate-integrity's escape-list rule — as a reviewed diff, at which point the intentionality the requirement asks about becomes their recorded decision. - 7.2.1 (ASVS 5.0.0,
lint) — The residual is scope, not mechanism: the lint rule matches the .auth.getSession member shape, so a consumer building a novel token path that never touches the Supabase client is caught by the web-security-reviewer's mandatory pass on auth seams, not by a machine. - 7.2.2 (ASVS 5.0.0,
auth-posture) — What is proven live is the web half only (the browser lane's cookie assertion); the mobile session pair is held in LargeSecureStore and asserted by unit tests, not a device run. Nothing structurally prevents a consumer from hand-rolling a static-key auth scheme in new code; that lands on the web-security-reviewer's mandatory paths rather than a gate. - 8.2.2 (ASVS 5.0.0,
schema-rls) — Residuals stated: tools/rls-exempt.json exemptions are a human-reviewed escape hatch; service_role bypasses RLS inside ADR-governed Edge Functions (REVOKE ALL by default, per-table ADR'd grants); and the gate proves predicate realness and form, never that a policy's business meaning is the right one for a consumer's new domain. - 8.4.1 (ASVS 5.0.0,
tenancy) — Residuals stated: the gate closes predicate form and the tenant key against schema drift, never the business question of which rows belong to which tenant in a consumer's new domain; tools/rls-exempt.json remains the reviewed escape; and 'never affect' is proven for the data plane the tests exercise, not for side channels such as timing or shared quotas. - 10.3.3 (ASVS 5.0.0,
schema-rls) — Residual stated plainly: the architecture has exactly one trusted issuer, and a consumer who federates additional issuers must add explicit iss discrimination that nothing here provides. - MASVS-NETWORK-1 (MASVS 2.1,
expo-policy) — What this does not reach: the Supabase project URL the mobile client dials (EXPO_PUBLIC_SUPABASE_URL, or extra.supabaseUrl if a consumer adds it) is scheme-checked by no gate (only extra.apiOrigin is), so a plain-http Supabase URL is refused at runtime by the ATS/cleartext posture the gate holds rather than by any check of the URL itself; a dependency's own transport (a native SDK carrying its own trust manager or URLSession configuration) is invisible to a config check; TLS version and cipher choices are the platform's; no lane captures live traffic; the web API host's HSTS is a web-side control (security-headers step) outside MASVS.