{ "pack_id": "security-review", "title": "Security review", "version": "0.1.0", "summary": "A collection of nouns and verbs for authorized, local-only security review of code: scope check, threat model, a 16-area catalog, sandbox reproduction, tested fixes and independent review, with a worked example of the finding checks.", "dependencies": [], "boundaries": [ "Review only code the requester owns or is explicitly authorized to review, from a local copy. Never scan, probe, exploit or load-test any running system, including the requester's own production.", "Findings go only to the requester. Disclosure to anyone else is the owner's separate decision.", "Report where a secret is, never its value. Never try a found credential.", "Importing the pack writes nothing and enqueues nothing." ], "nouns": [ { "slug": "pack", "category": "noun.skill_pack", "role": "pack", "title": "A collection of nouns and verbs for authorized, local-only security review of code", "value": { "lets_workers": "Review code you own or are authorized to review for security problems, reproduce them only in a local sandbox, propose tested fixes and have another worker check the findings, all privately.", "flow": [ { "verb": { "$verb": "security-review.check-scope" }, "when": "First, always; nothing else runs without a passing scope check." }, { "verb": { "$verb": "security-review.threat-model" }, "when": "After the scope check." }, { "verb": { "$verb": "security-review.review-code" }, "when": "Per priority area; areas can run as separate attempts." }, { "verb": { "$verb": "security-review.reproduce-locally" }, "when": "For findings worth confirming, in a sandbox only." }, { "verb": { "$verb": "security-review.propose-fix" }, "when": "For confirmed findings; a patch and a test, never pushed." }, { "verb": { "$verb": "security-review.review-findings" }, "when": "Last, by a different worker." } ], "rules": [ "Review only code the requester owns or is explicitly authorized to review, from a local copy. Never scan, probe, exploit or load-test any running system, including the requester's own production.", "Findings go only to the requester. Disclosure to anyone else is the owner's separate decision.", "Report where a secret is, never its value. Never try a found credential." ] }, "relations": [ [ "requires_noun", "scope-rules" ], [ "requires_noun", "check-catalog" ], [ "requires_noun", "severity-rubric" ], [ "requires_noun", "template.authorization" ], [ "requires_noun", "template.scope-check" ], [ "requires_noun", "template.threat-model" ], [ "requires_noun", "template.finding" ], [ "requires_noun", "template.reproduction" ], [ "requires_noun", "template.fix" ], [ "requires_noun", "template.review" ] ] }, { "slug": "scope-rules", "category": "noun.skill_pack", "role": "scope_rules", "title": "Scope rules for security review", "category_reason": "A reusable set of guardrails every verb in this pack must follow.", "value": { "rules": [ "Review only code the requester owns or is explicitly authorized to review, from a local copy. Never scan, probe, exploit or load-test any running system, including the requester's own production.", "Findings go only to the requester. Disclosure to anyone else is the owner's separate decision.", "Report where a secret is, never its value. Never try a found credential.", "The authorization noun names the requester, the target, the exact commit, the allowed activities and an expiry; an expired or missing authorization means blocked.", "Sandboxes have no credentials and no network beyond local services the sandbox itself starts.", "Never weaken a security control to make a reproduction or a test pass." ] } }, { "slug": "check-catalog", "category": "noun.benchmark_suite", "role": "check_catalog", "title": "Security check catalog: 16 areas", "category_reason": "A fixed catalog of review areas that every review is measured against.", "value": { "areas": [ { "id": "object-authorization", "asks": "Every read or write of a private resource checks the caller's right to that exact resource on the server." }, { "id": "authentication-sessions", "asks": "Credentials, tokens and sessions are created, stored, expired and revoked safely." }, { "id": "injection", "asks": "Untrusted input never reaches a SQL query, shell command, template or interpreter without parameterization or strict validation." }, { "id": "path-traversal", "asks": "User-controlled paths cannot escape their intended directory." }, { "id": "server-side-requests", "asks": "User-controlled URLs cannot make the server reach internal or unintended destinations." }, { "id": "unsafe-deserialization", "asks": "Untrusted bytes are never deserialized into executable objects." }, { "id": "output-encoding", "asks": "Untrusted text is encoded for its output context, so it cannot run as script in a browser." }, { "id": "cross-site-requests", "asks": "State-changing browser requests need proof they came from the site itself." }, { "id": "secrets-handling", "asks": "Secrets are not in code, logs, errors, client bundles or CI output." }, { "id": "dependency-advisories", "asks": "Known advisories are checked against reachable code paths, with the tool and database date." }, { "id": "ci-supply-chain", "asks": "CI never runs untrusted code with secrets or write tokens, and third-party actions are pinned." }, { "id": "cryptography", "asks": "Passwords use a slow salted hash, randomness comes from a secure source and no custom cryptography is used." }, { "id": "abuse-and-cost", "asks": "Expensive operations have rate limits and quotas so one caller cannot exhaust capacity or budget." }, { "id": "uploads", "asks": "Uploaded files have type, size and storage limits and are never executed or served unsafely." }, { "id": "sensitive-logging", "asks": "Logs omit personal data and credentials, and log retention is bounded." }, { "id": "agent-tool-boundaries", "asks": "Model and tool outputs, retrieved documents and task text are treated as data: they cannot widen a tool's permissions, choose destinations or become commands without checks." } ], "note": "agent-tool-boundaries covers systems where models or agents call tools; skip it otherwise." } }, { "slug": "severity-rubric", "category": "noun.benchmark_suite", "role": "severity_rubric", "title": "Severity rubric and deterministic finding checks", "category_reason": "A scoring rubric with deterministic checks and golden fixtures with recorded expected results.", "value": { "fixture_kind": "finding_checks", "severity_levels": { "critical": "Remote, unauthenticated compromise of data or systems, or exposure of credentials with broad access.", "high": "Unauthorized access to other users' data or actions with modest preconditions.", "medium": "Limited impact, or significant preconditions such as an existing account with special rights.", "low": "Defense in depth: hard to exploit or small impact.", "informational": "A risky pattern with no demonstrated impact." }, "confidence_rule": "High needs a local reproduction; reasoning from code alone is at most medium.", "finding_schema": { "type": "object", "additionalProperties": false, "required": [ "area", "title", "severity", "confidence", "location", "explanation", "reproduction", "fix", "status" ], "properties": { "area": { "type": "string", "enum": [ "object-authorization", "authentication-sessions", "injection", "path-traversal", "server-side-requests", "unsafe-deserialization", "output-encoding", "cross-site-requests", "secrets-handling", "dependency-advisories", "ci-supply-chain", "cryptography", "abuse-and-cost", "uploads", "sensitive-logging", "agent-tool-boundaries" ] }, "title": { "type": "string", "minLength": 1, "maxLength": 200 }, "severity": { "type": "string", "enum": [ "critical", "high", "medium", "low", "informational" ] }, "confidence": { "type": "string", "enum": [ "high", "medium", "low" ] }, "location": { "type": "string", "minLength": 1, "maxLength": 300 }, "explanation": { "type": "string", "minLength": 1, "maxLength": 1200 }, "reproduction": { "type": "string", "minLength": 1, "maxLength": 1500 }, "fix": { "type": "string", "minLength": 1, "maxLength": 800 }, "status": { "type": "string", "enum": [ "reproduced_locally", "reasoned_not_reproduced", "not_reproducible" ] } } }, "deterministic_checks": [ { "id": "area-known", "rule": { "rule": "enum", "path": "area", "values": [ "object-authorization", "authentication-sessions", "injection", "path-traversal", "server-side-requests", "unsafe-deserialization", "output-encoding", "cross-site-requests", "secrets-handling", "dependency-advisories", "ci-supply-chain", "cryptography", "abuse-and-cost", "uploads", "sensitive-logging", "agent-tool-boundaries" ] }, "why": "Findings map to the catalog." }, { "id": "severity-known", "rule": { "rule": "enum", "path": "severity", "values": [ "critical", "high", "medium", "low", "informational" ] }, "why": "Severity uses the rubric's levels." }, { "id": "located", "rule": { "rule": "present", "path": "location" }, "why": "Every finding points at code." }, { "id": "fix-present", "rule": { "rule": "present", "path": "fix" }, "why": "Every finding proposes a fix." }, { "id": "local-only", "rule": { "rule": "hosts_local_only", "path": "reproduction" }, "why": "Reproductions target only local sandboxes: every host named must be localhost, a loopback address or .invalid." }, { "id": "no-secret-values", "rule": { "rule": "pattern_absent", "path": "$", "pattern": "(?i:\\b(?:api[_-]?key|secret|token|password|passwd|pwd|access[_-]?key|client[_-]?secret)\\b[\"']?\\s*[:=]\\s*[\"']?[A-Za-z0-9_\\-/+=.]{8,})|(?i:\\bbearer\\s+[A-Za-z0-9_\\-.=+/]{12,})|\\b[A-Z0-9_]*(?:SECRET|TOKEN|PASSWORD|API_KEY)[A-Z0-9_]*\\s*=\\s*[^\\s\"']{8,}" }, "why": "Report where a secret is, never its value." } ], "golden_fixtures": [ { "id": "good-reproduced", "finding": { "area": "object-authorization", "title": "Any signed-in user can read another user's invoice", "severity": "high", "confidence": "high", "location": "app/routes/invoices.py:41-58", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "In a local sandbox build with two synthetic users, user B requested user A's invoice at http://localhost:8000/invoices/1 and received it.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" }, "label": "known_good" }, { "id": "good-reasoned", "finding": { "area": "agent-tool-boundaries", "title": "Retrieved page text can choose the fetch tool's next destination", "severity": "medium", "confidence": "medium", "location": "agent/tools/fetch.py:12-30", "explanation": "The fetch tool follows a URL extracted from the previous page's text with no allowlist.", "reproduction": "Not run: reasoning from code only. A local fixture page containing a link to http://127.0.0.1:9/ would show whether the tool follows it.", "fix": "Restrict destinations to the task's declared allowlist and treat page text as data.", "status": "reasoned_not_reproduced" }, "label": "known_good" }, { "id": "bad-live-target", "finding": { "area": "object-authorization", "title": "Invoice exposure confirmed on the live site", "severity": "high", "confidence": "high", "location": "app/routes/invoices.py:41-58", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "Requested https://billing.example.com/invoices/1 as a second user and received it.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" }, "label": "known_bad" }, { "id": "bad-secret-value", "finding": { "area": "secrets-handling", "title": "Deploy key committed", "severity": "high", "confidence": "high", "location": "deploy/config.env:3", "explanation": "The file contains password = hunter2hunter2hunter2 for the database.", "reproduction": "Read the file at the pinned commit.", "fix": "Remove it and rotate the credential.", "status": "reproduced_locally" }, "label": "known_bad" }, { "id": "bad-no-location", "finding": { "area": "object-authorization", "title": "Some route probably lacks checks", "severity": "high", "confidence": "high", "location": "", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "In a local sandbox build with two synthetic users, user B requested user A's invoice at http://localhost:8000/invoices/1 and received it.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" }, "label": "known_bad" }, { "id": "bad-userinfo-host", "finding": { "area": "object-authorization", "title": "Any signed-in user can read another user's invoice", "severity": "high", "confidence": "high", "location": "app/routes/invoices.py:41-58", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "Requested http://localhost@203.0.113.9/invoices/1 as a second user.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" }, "label": "known_bad" }, { "id": "bad-lookalike-host", "finding": { "area": "object-authorization", "title": "Any signed-in user can read another user's invoice", "severity": "high", "confidence": "high", "location": "app/routes/invoices.py:41-58", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "Requested http://localhost.attacker.example/invoices/1 as a second user.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" }, "label": "known_bad" }, { "id": "bad-wildcard-dns", "finding": { "area": "object-authorization", "title": "Any signed-in user can read another user's invoice", "severity": "high", "confidence": "high", "location": "app/routes/invoices.py:41-58", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "Requested http://127.0.0.1.nip.io:8000/invoices/1 as a second user.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" }, "label": "known_bad" }, { "id": "bad-bare-address", "finding": { "area": "object-authorization", "title": "Any signed-in user can read another user's invoice", "severity": "high", "confidence": "high", "location": "app/routes/invoices.py:41-58", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "Sent the request to 198.51.100.7:8080 from a second account.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" }, "label": "known_bad" }, { "id": "bad-bare-domain", "finding": { "area": "object-authorization", "title": "Any signed-in user can read another user's invoice", "severity": "high", "confidence": "high", "location": "app/routes/invoices.py:41-58", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "Requested billing.example.com/invoices/1 from a second account.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" }, "label": "known_bad" }, { "id": "bad-quoted-secret", "finding": { "area": "secrets-handling", "title": "Deploy key committed", "severity": "high", "confidence": "high", "location": "deploy/config.env:3", "explanation": "The file sets \"password\": \"hunter2hunter2\" for the database.", "reproduction": "Read the file at the pinned commit.", "fix": "Remove it and rotate the credential.", "status": "reproduced_locally" }, "label": "known_bad" } ], "expected": { "good-reproduced": { "verdict": "pass", "failed_checks": [] }, "good-reasoned": { "verdict": "pass", "failed_checks": [] }, "bad-live-target": { "verdict": "fail", "failed_checks": [ "local-only" ] }, "bad-secret-value": { "verdict": "fail", "failed_checks": [ "no-secret-values" ] }, "bad-no-location": { "verdict": "fail", "failed_checks": [ "located" ] }, "bad-userinfo-host": { "verdict": "fail", "failed_checks": [ "local-only" ] }, "bad-lookalike-host": { "verdict": "fail", "failed_checks": [ "local-only" ] }, "bad-wildcard-dns": { "verdict": "fail", "failed_checks": [ "local-only" ] }, "bad-bare-address": { "verdict": "fail", "failed_checks": [ "local-only" ] }, "bad-bare-domain": { "verdict": "fail", "failed_checks": [ "local-only" ] }, "bad-quoted-secret": { "verdict": "fail", "failed_checks": [ "no-secret-values" ] } } }, "relations": [ [ "requires_noun", "template.finding" ] ] }, { "slug": "template.authorization", "category": "noun.seed_hypothesis", "role": "template", "title": "Template: who authorized this review, for which target and commit, which activities, and until when", "value": { "describes": "who authorized this review, for which target and commit, which activities, and until when", "schema": { "type": "object", "additionalProperties": false, "required": [ "requester", "target", "commit", "basis", "allowed_activities", "expires_at" ], "properties": { "requester": { "type": "string", "minLength": 1, "maxLength": 200 }, "target": { "type": "string", "minLength": 1, "maxLength": 300 }, "commit": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[0-9a-f]{40}([0-9a-f]{24})?$" }, "basis": { "type": "string", "enum": [ "owner", "written_authorization" ] }, "evidence": { "type": "string", "minLength": 0, "maxLength": 400 }, "allowed_activities": { "type": "array", "minItems": 1, "maxItems": 3, "items": { "type": "string", "enum": [ "read_code", "run_tests_in_sandbox", "reproduce_in_sandbox" ] } }, "expires_at": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}", "maxLength": 40 } } }, "rules": [ "basis is owner or written_authorization with evidence.", "Expired means blocked." ] }, "category_reason": "The stated scope is a claim the scope check verifies before any review work." }, { "slug": "template.scope-check", "category": "noun.eval_run", "role": "template", "title": "Template: the result of checking a review's authorization against the snapshot", "value": { "describes": "the result of checking a review's authorization against the snapshot", "schema": { "type": "object", "additionalProperties": false, "required": [ "authorization_ref", "snapshot_ref", "checks", "verdict" ], "properties": { "authorization_ref": { "type": "string", "minLength": 1, "maxLength": 300 }, "snapshot_ref": { "type": "string", "minLength": 1, "maxLength": 300 }, "checks": { "type": "array", "minItems": 3, "maxItems": 3, "items": { "type": "object", "additionalProperties": false, "required": [ "id", "result" ], "properties": { "id": { "type": "string", "enum": [ "fields-match", "not-expired", "activities-listed" ] }, "result": { "type": "string", "enum": [ "pass", "fail" ] }, "note": { "type": "string", "minLength": 0, "maxLength": 300 } } } }, "verdict": { "type": "string", "enum": [ "confirmed", "blocked" ] } } }, "rules": [ "verdict is confirmed only when all three checks pass." ] }, "category_reason": "A scope check is a deterministic verification run." }, { "slug": "template.threat-model", "category": "noun.seed_hypothesis", "role": "template", "title": "Template: assets, entry points, trust boundaries, likely attackers and the areas to review first", "value": { "describes": "assets, entry points, trust boundaries, likely attackers and the areas to review first", "schema": { "type": "object", "additionalProperties": false, "required": [ "assets", "entry_points", "trust_boundaries", "attackers", "priority_areas" ], "properties": { "assets": { "type": "array", "minItems": 1, "maxItems": 20, "items": { "type": "string", "minLength": 1, "maxLength": 200 } }, "entry_points": { "type": "array", "minItems": 1, "maxItems": 40, "items": { "type": "object", "additionalProperties": false, "required": [ "name", "location" ], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 120 }, "location": { "type": "string", "minLength": 1, "maxLength": 300 } } } }, "trust_boundaries": { "type": "array", "minItems": 1, "maxItems": 20, "items": { "type": "string", "minLength": 1, "maxLength": 200 } }, "attackers": { "type": "array", "minItems": 1, "maxItems": 10, "items": { "type": "string", "minLength": 1, "maxLength": 200 } }, "priority_areas": { "type": "array", "minItems": 1, "maxItems": 16, "items": { "type": "string", "enum": [ "object-authorization", "authentication-sessions", "injection", "path-traversal", "server-side-requests", "unsafe-deserialization", "output-encoding", "cross-site-requests", "secrets-handling", "dependency-advisories", "ci-supply-chain", "cryptography", "abuse-and-cost", "uploads", "sensitive-logging", "agent-tool-boundaries" ] } } } }, "rules": [ "Every entry point cites its location in code." ] }, "category_reason": "A threat model is a set of hypotheses about how the system could be attacked." }, { "slug": "template.finding", "category": "noun.seed_hypothesis", "role": "template", "title": "Template: one security finding: area, severity, confidence, location, local reproduction and fix", "value": { "describes": "one security finding: area, severity, confidence, location, local reproduction and fix", "schema": { "type": "object", "additionalProperties": false, "required": [ "area", "title", "severity", "confidence", "location", "explanation", "reproduction", "fix", "status" ], "properties": { "area": { "type": "string", "enum": [ "object-authorization", "authentication-sessions", "injection", "path-traversal", "server-side-requests", "unsafe-deserialization", "output-encoding", "cross-site-requests", "secrets-handling", "dependency-advisories", "ci-supply-chain", "cryptography", "abuse-and-cost", "uploads", "sensitive-logging", "agent-tool-boundaries" ] }, "title": { "type": "string", "minLength": 1, "maxLength": 200 }, "severity": { "type": "string", "enum": [ "critical", "high", "medium", "low", "informational" ] }, "confidence": { "type": "string", "enum": [ "high", "medium", "low" ] }, "location": { "type": "string", "minLength": 1, "maxLength": 300 }, "explanation": { "type": "string", "minLength": 1, "maxLength": 1200 }, "reproduction": { "type": "string", "minLength": 1, "maxLength": 1500 }, "fix": { "type": "string", "minLength": 1, "maxLength": 800 }, "status": { "type": "string", "enum": [ "reproduced_locally", "reasoned_not_reproduced", "not_reproducible" ] } } }, "rules": [ "Must pass every deterministic check in the severity rubric.", "Reproductions target local sandboxes only." ], "example": { "area": "object-authorization", "title": "Any signed-in user can read another user's invoice", "severity": "high", "confidence": "high", "location": "app/routes/invoices.py:41-58", "explanation": "The handler loads the invoice by id and returns it without comparing its owner with the caller.", "reproduction": "In a local sandbox build with two synthetic users, user B requested user A's invoice at http://localhost:8000/invoices/1 and received it.", "fix": "Compare invoice.owner_id with the caller's id before returning; add a test that user B is refused.", "status": "reproduced_locally" } }, "category_reason": "A finding is a hypothesis about a weakness, confirmed or not by reproduction." }, { "slug": "template.reproduction", "category": "noun.eval_run", "role": "template", "title": "Template: a local sandbox reproduction of one finding", "value": { "describes": "a local sandbox reproduction of one finding", "schema": { "type": "object", "additionalProperties": false, "required": [ "finding_ref", "environment", "steps", "result", "artifacts_sha256" ], "properties": { "finding_ref": { "type": "string", "minLength": 1, "maxLength": 300 }, "environment": { "type": "string", "minLength": 1, "maxLength": 400 }, "steps": { "type": "array", "minItems": 1, "maxItems": 20, "items": { "type": "string", "minLength": 1, "maxLength": 300 } }, "result": { "type": "string", "enum": [ "reproduced", "not_reproduced", "inconclusive" ] }, "artifacts_sha256": { "type": "array", "minItems": 0, "maxItems": 10, "items": { "type": "string", "pattern": "^[0-9a-f]{64}$" } } } }, "rules": [ "The environment names the sandbox and confirms it had no credentials." ] }, "category_reason": "A reproduction is a recorded run with artifact digests." }, { "slug": "template.fix", "category": "noun.code_node", "role": "template", "title": "Template: a proposed patch with its tests, stored by digest and never pushed", "value": { "describes": "a proposed patch with its tests, stored by digest and never pushed", "schema": { "type": "object", "additionalProperties": false, "required": [ "finding_ref", "patch_sha256", "files", "tests_added", "tests_passed" ], "properties": { "finding_ref": { "type": "string", "minLength": 1, "maxLength": 300 }, "patch_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "files": { "type": "array", "minItems": 1, "maxItems": 30, "items": { "type": "string", "minLength": 1, "maxLength": 300 } }, "tests_added": { "type": "array", "minItems": 1, "maxItems": 10, "items": { "type": "string", "minLength": 1, "maxLength": 300 } }, "tests_passed": { "type": "boolean" }, "notes": { "type": "string", "minLength": 0, "maxLength": 600 } } }, "rules": [ "tests_passed comes from an actual run.", "The patch is not pushed, merged or opened as a pull request by this pack." ] }, "category_reason": "A fix is a code artifact pinned by digest with its test evidence." }, { "slug": "template.review", "category": "noun.eval_run", "role": "template", "title": "Template: an independent review of the findings", "value": { "describes": "an independent review of the findings", "schema": { "type": "object", "additionalProperties": false, "required": [ "checked", "verdict", "reasons" ], "properties": { "checked": { "type": "array", "minItems": 1, "maxItems": 60, "items": { "type": "object", "additionalProperties": false, "required": [ "finding_ref", "result" ], "properties": { "finding_ref": { "type": "string", "minLength": 1, "maxLength": 300 }, "result": { "type": "string", "enum": [ "upheld", "downgraded", "rejected" ] }, "note": { "type": "string", "minLength": 0, "maxLength": 400 } } } }, "verdict": { "type": "string", "enum": [ "accept", "revise", "reject" ] }, "reasons": { "type": "array", "minItems": 1, "maxItems": 8, "items": { "type": "string", "minLength": 1, "maxLength": 300 } } } }, "rules": [ "The reviewer did not write the findings." ] }, "category_reason": "A review is a verification run over the findings." } ], "verbs": [ { "slug": "check-scope", "kind": "verb.verify_gate", "title": "Check the review is authorized", "claimant": "agent", "summary": "Confirm the authorization covers this requester, target, commit and activities and has not expired, before any review work.", "outcome": "scope_confirmed, or blocked with the exact missing authorization.", "ready_outcome": "scope_confirmed", "model_use": "none", "pinned": [ "scope-rules" ], "slots": [ { "name": "authorization", "category": "noun.seed_hypothesis", "description": "Pin of the authorization noun." }, { "name": "repo_snapshot", "category": "noun.public_source", "description": "Pin of the local snapshot to review, shaped like repo-review's snapshot template." } ], "produces": [ { "name": "authorization_check", "template": "template.scope-check" } ], "steps": [ "Verify both pins.", "Compare requester, target and commit between the authorization and the snapshot.", "Return blocked if anything is missing, mismatched or expired. Never assume permission." ], "acceptance": [ { "id": "fields-match", "check": "Target and commit in the authorization equal the snapshot's.", "method": "deterministic" }, { "id": "not-expired", "check": "expires_at is after the claim time.", "method": "deterministic" }, { "id": "activities-listed", "check": "allowed_activities names every activity later verbs will need.", "method": "deterministic" } ], "bounds": { "max_elapsed_seconds": 300 }, "network": [ "none", "None beyond reading the local copy. No requests to any deployed system." ] }, { "slug": "threat-model", "kind": "verb.situate", "title": "Sketch the threat model", "claimant": "agent", "summary": "List assets, entry points, trust boundaries and likely attackers, and choose the catalog areas to review first.", "outcome": "A threat model.", "ready_outcome": "model_ready", "pinned": [ "scope-rules", "check-catalog" ], "slots": [ { "name": "authorization_check", "category": "noun.eval_run", "description": "Pin of the passing scope check." }, { "name": "repo_snapshot", "category": "noun.public_source", "description": "Pin of the local snapshot." } ], "produces": [ { "name": "threat_model", "template": "template.threat-model" } ], "steps": [ "Verify the pins and that the scope check passed.", "Cite the code location of every entry point.", "Pick priority areas from the catalog with a reason each.", "Review only code the requester owns or is explicitly authorized to review, from a local copy. Never scan, probe, exploit or load-test any running system, including the requester's own production." ], "acceptance": [ { "id": "model-matches-template", "check": "The threat model validates against template.threat-model's schema.", "method": "deterministic" }, { "id": "areas-from-catalog", "check": "Every priority area is a catalog id.", "method": "deterministic" }, { "id": "plausible", "check": "Assets and attackers fit what the code actually does.", "method": "judgment" } ], "bounds": { "max_elapsed_seconds": 1200 }, "network": [ "none", "None beyond reading the local copy. No requests to any deployed system." ], "follows": [ "security-review.check-scope" ] }, { "slug": "review-code", "kind": "verb.solve_draft", "title": "Review one area of the code", "claimant": "agent", "summary": "Review the code for one catalog area and write findings with locations, severity, confidence and fixes.", "outcome": "Findings for the area, or no_change when the area holds up.", "ready_outcome": "findings_ready", "pinned": [ "scope-rules", "check-catalog", "severity-rubric" ], "slots": [ { "name": "threat_model", "category": "noun.seed_hypothesis", "description": "Pin of the threat model." }, { "name": "repo_snapshot", "category": "noun.public_source", "description": "Pin of the local snapshot." } ], "params": { "area": { "schema": { "type": "string", "enum": [ "object-authorization", "authentication-sessions", "injection", "path-traversal", "server-side-requests", "unsafe-deserialization", "output-encoding", "cross-site-requests", "secrets-handling", "dependency-advisories", "ci-supply-chain", "cryptography", "abuse-and-cost", "uploads", "sensitive-logging", "agent-tool-boundaries" ] }, "description": "The one catalog area this attempt reviews.", "required": true } }, "produces": [ { "name": "findings", "template": "template.finding", "max": 12 } ], "steps": [ "Verify the pins. Read code only for this area.", "Run the severity rubric's deterministic checks on every finding before writing it.", "Mark a finding reasoned_not_reproduced unless a later reproduction confirms it.", "Review only code the requester owns or is explicitly authorized to review, from a local copy. Never scan, probe, exploit or load-test any running system, including the requester's own production.", "Report where a secret is, never its value. Never try a found credential.", "Findings go only to the requester. Disclosure to anyone else is the owner's separate decision." ], "acceptance": [ { "id": "findings-match-template", "check": "Every finding validates against template.finding's schema.", "method": "deterministic" }, { "id": "rubric-checks", "check": "Every finding passes the severity rubric's deterministic checks.", "method": "deterministic" }, { "id": "area-only", "check": "Every finding's area equals the area parameter.", "method": "deterministic" }, { "id": "severity-justified", "check": "Severity follows the rubric's definitions.", "method": "judgment" } ], "bounds": { "max_elapsed_seconds": 2400, "max_findings": 12 }, "network": [ "none", "None beyond reading the local copy. No requests to any deployed system." ], "follows": [ "security-review.threat-model" ] }, { "slug": "reproduce-locally", "kind": "verb.verify_gate", "title": "Reproduce a finding locally", "claimant": "agent", "summary": "Build the pinned commit in a sandbox with synthetic data and no credentials, and try to reproduce one finding.", "outcome": "A reproduction record: reproduced, not reproduced or inconclusive.", "ready_outcome": "reproduction_recorded", "pinned": [ "scope-rules" ], "slots": [ { "name": "finding", "category": "noun.seed_hypothesis", "description": "Pin of the finding." }, { "name": "authorization_check", "category": "noun.eval_run", "description": "Pin of the passing scope check." }, { "name": "repo_snapshot", "category": "noun.public_source", "description": "Pin of the local snapshot." } ], "produces": [ { "name": "reproduction", "template": "template.reproduction" } ], "steps": [ "Confirm reproduce_in_sandbox is an allowed activity; otherwise return blocked.", "Run only inside the sandbox against services the sandbox starts, with synthetic users and data.", "Record each step and the result; store artifacts by digest.", "Review only code the requester owns or is explicitly authorized to review, from a local copy. Never scan, probe, exploit or load-test any running system, including the requester's own production.", "Report where a secret is, never its value. Never try a found credential." ], "acceptance": [ { "id": "record-matches-template", "check": "The reproduction validates against template.reproduction's schema.", "method": "deterministic" }, { "id": "local-only", "check": "Every address in the steps is localhost, 127.0.0.1, ::1 or example.invalid.", "method": "deterministic" }, { "id": "no-credentials", "check": "The environment states that no real credential was present.", "method": "deterministic" } ], "bounds": { "max_elapsed_seconds": 2400 }, "network": [ "local_only", "Only services the sandbox itself starts." ], "capabilities": [ "read permitted noun versions", "an isolated sandbox without credentials", "write candidate nouns in the requester's scope" ], "follows": [ "security-review.review-code" ] }, { "slug": "propose-fix", "kind": "verb.solve_draft", "title": "Propose a tested fix", "claimant": "agent", "summary": "Write the smallest patch that fixes a confirmed finding plus a test that fails before and passes after, without pushing anything.", "outcome": "A fix noun pinned by patch digest, or no_change when the fix belongs to the owner's design decision.", "ready_outcome": "fix_ready", "pinned": [ "scope-rules" ], "slots": [ { "name": "finding", "category": "noun.seed_hypothesis", "description": "Pin of the finding." }, { "name": "reproduction", "category": "noun.eval_run", "description": "Pin of its reproduction.", "required": false }, { "name": "repo_snapshot", "category": "noun.public_source", "description": "Pin of the local snapshot." } ], "produces": [ { "name": "fix", "template": "template.fix" } ], "steps": [ "Write a test that fails on the pinned commit, then the smallest patch that makes it pass.", "Run the existing test suite in the sandbox. Never weaken another control.", "Store the patch by digest. Do not push, merge or open a pull request." ], "acceptance": [ { "id": "fix-matches-template", "check": "The fix validates against template.fix's schema.", "method": "deterministic" }, { "id": "test-fails-then-passes", "check": "The added test failed before the patch and passed after it.", "method": "deterministic" }, { "id": "suite-passes", "check": "tests_passed is true from an actual sandbox run.", "method": "deterministic" } ], "bounds": { "max_elapsed_seconds": 2400 }, "network": [ "none", "None beyond reading the local copy. No requests to any deployed system." ], "follows": [ "security-review.reproduce-locally" ] }, { "slug": "review-findings", "kind": "verb.verify_gate", "title": "Independently review the findings", "claimant": "agent", "summary": "A different worker reruns the rubric checks and decides whether each finding is upheld, downgraded or rejected.", "outcome": "A review with a verdict.", "ready_outcome": "review_ready", "pinned": [ "severity-rubric", "scope-rules" ], "slots": [ { "name": "findings", "category": "noun.seed_hypothesis", "description": "Pins of the findings.", "many": true, "max": 60 }, { "name": "reproductions", "category": "noun.eval_run", "description": "Pins of reproductions.", "many": true, "max": 60, "required": false } ], "produces": [ { "name": "review", "template": "template.review" } ], "steps": [ "Confirm you wrote none of the findings; otherwise return blocked.", "Rerun every deterministic check.", "Downgrade confidence for findings without reproduction; reject findings that break the scope rules.", "Findings go only to the requester. Disclosure to anyone else is the owner's separate decision." ], "acceptance": [ { "id": "review-matches-template", "check": "The review validates against template.review's schema.", "method": "deterministic" }, { "id": "distinct-reviewer", "check": "The reviewing key differs from the keys that wrote the findings.", "method": "deterministic" }, { "id": "scope-enforced", "check": "Any finding whose reproduction touched a non-local address is rejected.", "method": "deterministic" } ], "bounds": { "max_elapsed_seconds": 1800 }, "network": [ "none", "None beyond reading the local copy. No requests to any deployed system." ], "review": "distinct_reviewer", "follows": [ "security-review.propose-fix" ] } ] }