security-review
Generated at build time from
skills/security-review/SKILL.md. Do not edit this page directly.
Security Review exists to find meaningful security failures introduced or exposed by a change.
Δ → Graph → Security<P, T, E>│ │ │ │ ││ │ │ │ └─ evidence that the property fails or holds (§10)│ │ │ └──── reachable attacker / trust path (§4-9)│ │ └─────── protected asset or security property (§3)│ ││ └─ nodes = actors, boundaries, controls, assets, sinks│ edges = authority and untrusted/sensitive data flow│└─ changed behavior, configuration, dependency, or exposure§1 Gate invoke only when security-relevant behavior changed§2 Delta smallest affected security graph§3 P protected asset and required security property§4 Authority actor → authorization → protected effect§5 Data untrusted source → transformation → sensitive sink§6 Secrets sensitive-data flow and exposure boundaries§7 Boundary external systems, network, files, webhooks, configuration§8 Supply dependency and build/release security applicability§9 Abuse adversarial availability / resource abuse only when relevant§10 E evidence-backed reachable finding§11 Proof targeted security verification; test-engineering if complex§12 Handoff architecture/control changes go to the owning skillStart from the change, not a vulnerability catalog.
Ask:
What security property must remain true?What can an untrusted or less-privileged actor reach now?What authority can they exercise?What sensitive data can flow?What privileged effect can occur?Then trace the smallest realistic path from attacker capability to protected asset/effect.
If there is no reachable path, broken control, and meaningful impact, there is no security finding.
1. Applicability gate
Section titled “1. Applicability gate”security-review is a specialist capability, not a mandatory stage.
Invoke it when a change materially touches:
authenticationauthorization / RBAC / ABACsession managementcookies / tokens / JWTpassword / credential handling
tenant or user isolationownership checksadmin / privileged operationsimpersonation / delegated authority
user-controlled input reaching:- database/query- HTML/template output- shell/process execution- filesystem/path- URL/network request- parser/deserializer- redirect- dynamic code/config
file upload/downloadsecrets / key managementcryptographysensitive/private datapayment or security-sensitive workflows
public API exposureCORS / CSRFwebhooksOAuth/OIDCexternal integrationsrate / abuse controls
security configurationIAM / permissionspublic/private exposuredependency changes with meaningful security impactnew trust boundaryDo not invoke deep security review by default for:
formattingrenamingCSS/layoutdocumentationmechanical refactorstrivial type changesinternal mapping codelocal changes that do not alter:- trust- authority- exposure- sensitive data flow- privileged effectsNormal code-review remains responsible for noticing when a change should escalate.
Canonical trigger:
If a change modifieswhat an untrusted actor can reach,what authority an actor has,what sensitive data can flow,or what privileged effect can occur,security-review becomes relevant.2. Scope the changed security graph
Section titled “2. Scope the changed security graph”Default to diff-based review when a change set exists.
Build only the affected graph:
untrusted / less-trusted actor ↓entry point ↓authentication / identity ↓authorization / policy ↓validation / normalization ↓business operation ↓sensitive state / privileged effect / external sinkAlso trace configuration or dependency edges when they change effective security behavior.
Inspect surrounding code only far enough to establish:
who controls the input/authoritywhere trust changeswhich control is supposed to stop misusewhich asset/effect is reachablewhat actually happensDo not turn every PR into a whole-application penetration review.
Use broader baseline/threat-based review only when justified:
new applicationmajor security-sensitive redesignnew tenant/isolation modellarge trust-boundary changelegacy system onboardingpost-incident investigationexplicit security auditFor baseline work, map the relevant application trust zones, assets, privileged workflows, external boundaries, and existing controls before looking for attack paths.
3. Define P: asset and required security property
Section titled “3. Define P: asset and required security property”Do not begin with vulnerability names.
Begin with:
What are we protecting?Who is allowed to do what?What input is untrusted?What boundary is crossed?What must never become possible?Examples:
User A must never read or modify User B's private record.
A normal user must not invoke an administrator-only operation.
An unauthenticated caller must not create privileged state.
Uploaded content must not escape the intended storage boundary.
A user-controlled network destination must not expose internal-only resources.
A webhook replay must not duplicate a privileged effect.
Secrets must not reach client output, logs, traces, source artifacts, or third parties.
A tenant-scoped worker must not operate on another tenant's objects.Write the property before judging the implementation.
Only inspect controls that trace to a real asset/property/threat.
If the property itself is missing or ambiguous because the architecture does not define the trust boundary, escalate that design gap to engineering-design.
4. Trace authority to the protected effect
Section titled “4. Trace authority to the protected effect”Authentication answers:
Who is this actor?Authorization answers:
May this actor perform this action on this resource?For every changed privileged operation trace:
actor ↓identity/session ↓requested resource/action ↓authorization decision ↓protected effectAuthorization must hold at the server-side effect boundary.
Do not accept authorization that exists only:
in the UIin hidden/disabled controlsin client-side statein routing/navigationin a previous unrelated requestin a guessed role from client inputPay special attention when changed behavior touches:
object ownershipIDOR / BOLA-style resource accesstenant isolationadmin/user transitionsbulk operationsindirect referencesalternate API pathsbackground jobs acting for usersimpersonationdelegated authorityresource creation followed by mutationPrefer deny-by-default semantics when access is not explicitly granted.
Check the actual resource/action pair, not merely whether the actor is authenticated.
For multi-step workflows, confirm authorization is preserved across every step that can produce the protected effect.
5. Trace untrusted data to sensitive sinks
Section titled “5. Trace untrusted data to sensitive sinks”Use source → transformation → sink reasoning.
SOURCEuser inputrequest body/query/headerURLuploaded fileexternal API responsewebhookstored untrusted contentenvironment/config from a less-trusted source
↓
TRANSFORMATIONparsecanonicalizevalidatenormalizeauthorizeencodemap to safe primitive
↓
SINKdatabase/queryHTML/templatefilesystem/pathcommand/processnetwork requestredirectlogdeserializerdynamic code/configprivileged state transitionDo not report “missing validation” without explaining the actual path.
For every suspected issue establish:
attacker-controlled value ↓crossed boundary ↓sensitive operation ↓broken propertyReason about the actual library/framework semantics in use.
Do not infer a vulnerability merely because a source and sink both exist.
6. Respect trusted security primitives
Section titled “6. Respect trusted security primitives”Do not ask application code to reimplement protections already correctly provided by established framework/library primitives.
Examples:
parameterized database APIframework output escapingstandard password hashing libraryframework CSRF middlewaremature session implementationwell-established cryptographic primitiveReview whether the primitive is:
used correctlyused on every required pathbypasseddisabledmisconfiguredfed invalid assumptionswrapped in a way that removes its guaranteePrefer secure defaults over custom hardening steps.
Do not invent custom cryptography, sanitizers, authentication protocols, token formats, or authorization frameworks when a trusted mechanism already satisfies the property.
If cryptography changes materially, verify purpose, primitive/library, key lifecycle, nonce/IV rules, rotation/revocation implications, failure handling, and compatibility. Escalate specialized cryptographic design when needed.
7. Trace secrets and sensitive data
Section titled “7. Trace secrets and sensitive data”Sensitive data is a flow problem.
Classify only data relevant to the change:
credentialsession/tokenprivate keyAPI secretpersonal/private recordpayment/security-sensitive datatenant-confidential datainternal security metadataTrace:
source ↓processing ↓storage ↓transport ↓telemetry ↓client/third partyVerify it does not unintentionally reach:
source controlclient bundleHTML/client responselogstracesmetrics labelserror messagesanalyticsURLs/query stringsthird-party systemsbuild artifactscache keys or debug dumpsTelemetry is another data boundary.
Do not improve diagnosis by logging a secret or sensitive payload that does not belong there.
For stored/transmitted sensitive data, check only the protections required by the product/system property. Do not demand “encrypt everything” by ritual.
8. Review changed external and configuration boundaries
Section titled “8. Review changed external and configuration boundaries”Configuration is part of the security graph when it changes effective authority or exposure.
Review relevant changes to:
CORScookiesTLSauthentication modesession settingspublic/private exposurenetwork accessIAM / permissionssecret injectiondebug/development modestorage permissionssecurity headersdeployment environmentproxy/trust settingsAsk:
Did the effective trust boundary move?Did a previously private resource become reachable?Did authority broaden?Did a secure default become opt-in or disabled?Network destinations / SSRF-sensitive flows
Section titled “Network destinations / SSRF-sensitive flows”When attacker-controlled data influences an outbound request, establish the required destination policy.
Trace:
attacker-controlled destination ↓parse / canonicalize ↓scheme + host + port resolution ↓redirect behavior ↓DNS / network destination ↓requestWhen only known destinations are valid, prefer explicit allowlisting and server-constructed requests.
When arbitrary public destinations are a product requirement, verify controls that keep internal/private/unsafe destinations out of reach and account for redirect/resolution behavior relevant to the implementation.
Do not label every URL field “SSRF”; prove the server actually performs a reachable request under attacker influence.
When untrusted input affects a path or upload:
original name/input ↓server-side identity/path decision ↓type/size/content checks required by the product ↓storage boundary ↓serving/download boundaryDo not let user-supplied paths define arbitrary filesystem locations.
Review traversal/canonicalization, executable serving, access control, and storage exposure only where relevant to the actual file workflow.
Webhooks / callbacks
Section titled “Webhooks / callbacks”Trace:
sender identity/authenticity ↓payload validation ↓replay/duplicate semantics ↓authorization/business rule ↓privileged effectDo not assume signature verification alone makes a replay-sensitive effect safe.
9. Review dependencies and supply-chain changes by applicability
Section titled “9. Review dependencies and supply-chain changes by applicability”A scanner finding is a lead, not automatically a security finding.
For a changed dependency ask:
Was the package/version actually added or changed? ↓Does the advisory apply to this version/configuration? ↓Is the vulnerable capability present? ↓Is it reachable in this application/deployment? ↓Can an attacker satisfy the required preconditions? ↓What is the realistic impact?Prioritize reachable/applicable risk.
Do not block solely because:
a CVE existsa scanner reports "high"a transitive dependency is presentwithout understanding applicability.
Escalate quickly when the change indicates:
known malicious or compromised packagedependency provenance/integrity failurecredential or signing-key exposurebuild/release integrity compromisecritical remotely reachable vulnerable functionalityunexpected dependency substitution/typosquattingSupply-chain protection for build artifacts, provenance, signing, and release integrity belongs primarily to release-engineering; Security Review identifies the security property/risk.
Automated dependency review/SCA is useful for discovering candidate issues. Manual review decides whether a candidate is relevant to the changed application path.
10. Treat adversarial availability separately from capacity
Section titled “10. Treat adversarial availability separately from capacity”Normal latency, capacity, autoscaling, and organic traffic saturation belong to production-ops.
Security Review owns availability when an attacker can intentionally create disproportionate impact through the changed behavior.
Examples:
unbounded expensive requestcredential brute forceunbounded uploadresource exhaustionfan-out/amplificationalgorithmic complexity abusemissing rate/abuse boundary on privileged or costly operationsreplay causing repeated expensive effectsTrace:
attacker cost ↓reachable operation ↓system/resource cost ↓existing bound/control ↓impactDo not demand rate limiting for every endpoint.
Add an abuse control only when the attacker/resource asymmetry justifies it.
11. Use threat frameworks as challenge libraries, not proof
Section titled “11. Use threat frameworks as challenge libraries, not proof”OWASP Top 10, ASVS, CWE, STRIDE, and similar frameworks can help challenge the affected graph.
Use them after the graph is known:
affected asset/property ↓reachable trust/authority/data path ↓relevant threat categories ↓challenge existing controlsDo not:
walk every ASVS item for a CSS changerun STRIDE on every CRUD patchreport a vulnerability because it matches a CWE nameadd controls only to satisfy a checklistFor broad/baseline security review, a structured threat model is appropriate because design-level risks and forgotten attack paths are part of the scope.
For normal PR review, keep threat reasoning on the changed subgraph.
Vulnerability names are classification after understanding, not evidence before understanding.
12. Require evidence for every finding
Section titled “12. Require evidence for every finding”Every finding must establish:
Location ↓Security property ↓Attacker capability / trust assumption ↓Actual authority/data flow ↓Broken or missing control ↓Reachable failure path ↓Impact ↓Smallest corrective directionMinimum form:
[Severity] file:line — concise security issue
Property:<what must remain protected>
Actual:<what the implementation currently allows>
Attack/failure path:<minimal realistic reachable path>
Impact:<unauthorized capability, exposure, integrity loss, or abuse>
Fix:<smallest change that restores the property>Do not report a theoretical vulnerability merely because code resembles a dangerous pattern.
If a suspected path is cheap and safe to verify, run the smallest targeted check.
If evidence falsifies the suspicion, remove the finding.
State residual uncertainty explicitly when reachability or deployment context cannot be established.
13. Assign severity from realistic impact and reachability
Section titled “13. Assign severity from realistic impact and reachability”Use the same review language as code-review:
Critical
Section titled “Critical”A reachable issue can plausibly cause severe impact such as:
broad authentication/authorization bypasscross-tenant or large-scale sensitive-data exposureremote code execution in the deployed contextcredential/signing-key compromisedestructive integrity failure with large blast radiusbuild/release integrity compromiseA concrete reachable weakness can cause:
unauthorized access/actionmeaningful private-data exposureprivilege escalation with bounded scopesecurity-sensitive workflow bypassreal injection/path/network boundary violationreplay/abuse with meaningful effectmaterial security regressionA real security weakness with limited scope/impact, for example:
narrow information exposurelocalized hardening gap with reachable but constrained impactmissing defensive control on a low-risk pathtest gap around an already-correct important security propertySeverity is not copied blindly from a scanner/CVE.
Consider attacker capability, reachability, preconditions, privilege level, data/effect scope, blast radius, and compensating controls.
14. Design targeted executable proof
Section titled “14. Design targeted executable proof”Security Review owns:
which security property matterswhich attack/trust path threatens itFor obvious verification:
simple policy decision→ targeted unit test
API authorization / tenant isolation→ integration test
real parser/validation boundary→ unit or integration at that boundary
database-enforced isolation→ real DB integration test
multi-step browser/session security workflow→ targeted E2E only when lower levels cannot prove itExamples:
anonymous→ privileged endpoint→ denied
User B→ User A's resource→ denied
revoked session→ protected action→ denied
untrusted path→ outside allowed root→ rejected
replayed webhook→ privileged effect occurs at most onceIf verification itself requires non-trivial environment, concurrency, protocol, failure injection, or boundary design:
security-review→ property + reachable attack path→ test-engineeringDo not recreate testing architecture here.
Do not create a giant security suite when one faithful regression proof protects the property.
15. Keep ownership boundaries clean
Section titled “15. Keep ownership boundaries clean”engineering-design
Section titled “engineering-design”Owns:
trust boundariesstate ownershipsystem-level security guaranteesarchitectureSecurity Review asks whether the implementation/change violates them.
If the correct fix requires a new trust boundary, different state owner, different isolation model, or new architectural control:
security-review→ finding/property→ engineering-designdesign-thinking
Section titled “design-thinking”Owns implementation of security controls inside the software graph.
code-review
Section titled “code-review”Owns general correctness/maintainability review and detects whether deeper security review is warranted.
code-review→ changed trust/authority/data boundary?→ security-reviewtest-engineering
Section titled “test-engineering”Owns complex executable proof.
security-review→ property / attack path
test-engineering→ smallest faithful proofrelease-engineering
Section titled “release-engineering”Owns build/deploy/release mechanics and protections such as artifact/release integrity where those are part of the shipping system.
production-ops
Section titled “production-ops”Owns runtime detection, diagnosis, mitigation, and recovery.
Security Review can identify security-relevant telemetry or operational properties, but monitoring/incident mechanics belong to production-ops.
16. Review-only vs remediation
Section titled “16. Review-only vs remediation”For an explicit request:
"security-review this PR/change"default:
inspect→ prove findings→ report→ do not modify codeWhen the parent task explicitly asks to review and fix, or Security Review is an internal stage of implementation:
inspect→ finding→ smallest effective control→ targeted verification→ re-review affected security graphDo not broaden remediation into unrelated hardening.
Prefer:
smallest effective control+smallest faithful proof+clear residual risk17. Output and persistence
Section titled “17. Output and persistence”Lead with actionable findings ordered by severity.
Critical- ...
Major- ...
Minor- ...Each finding must include the security property, reachable path, impact, and corrective direction.
After findings, optionally include:
Verified- targeted security checks actually performed
Residual risk- material uncertainty that could not be resolvedIf there are no evidence-backed findings:
No actionable security findings.Do not manufacture security feedback.
Do not create .agents/security.md, SECURITY_REVIEW.md, or threat-model.md by default for every change.
Per-change review evidence belongs in the PR/task/review context.
Durable system security properties belong in .agents/engineering.md.
Consequential security architecture decisions belong in ADRs.
Create a durable threat/security artifact only when a baseline audit, major architecture, compliance requirement, or explicit task actually needs one.
Proportionality
Section titled “Proportionality”Depth follows security risk, not diff size.
mechanical / non-security change→ no dedicated security-review
normal feature with unchanged trust/exposure→ code-review security awareness only
auth / authorization / sensitive input/data change→ focused review of affected security graph
new external boundary / tenant model / privileged workflow→ deeper review + targeted proof
major security architecture change / incident / explicit audit→ broader threat-based reviewA five-line authorization change can deserve deeper review than a thousand-line internal refactor.
Anti-goals
Section titled “Anti-goals”Security Review is not:
OWASP checklist completionmandatory STRIDE ceremony"sanitize everything""encrypt everything"one security test per endpointone threat model per PRcustom crypto designcustom auth framework designCVE severity copyingscanner finding = vulnerabilityspeculative attacker storieswhole-app pentest for every changesecurity theaterFrameworks and scanners are inputs.
Reachable security properties and evidence determine findings.