Maps a code change to the security tests worth running against it. Classifies changed paths and file contents into nine attack surfaces (authentication, session management, input handling, file upload, deserialization, access control, API and web service, cryptography, data protection), attaches the matching OWASP ASVS 4.0.3 verification requirements, OWASP Top 10 2021 category IDs, and OWASP WSTG section numbers to each active surface, then emits a per-surface manual and automated test checklist bounded by what actually changed. Surfaces with no changed lines are excluded rather than carried as filler. Use when a pull request, release branch, or feature is about to be security tested and the team needs a targeted test list instead of a generic application-wide checklist.
68
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
A change set has an attack surface: the set of security-relevant behaviors its files participate
in. A migration adding an avatar_url column and one adding a password_reset_token column
look identical in a diff stat and need entirely different tests. This skill turns a change set
into a bounded security test checklist in four moves:
What this owns: the mapping from a specific change to the specific security tests worth running against it, expressed as checkable items with standards references.
What it deliberately is not:
All requirement IDs below use OWASP ASVS 4.0.3 numbering. ASVS renumbers requirements between major versions, so an ID with no version attached is ambiguous. ASVS 5.0.0 was released on 2025-05-30 and 4.0.3 remains published as the previous stable release (OWASP ASVS project page). On a project standardized on 5.0.0, treat the chapter names below as the lookup key and re-resolve the numbers against that edition; the surfaces and test items do not change.
ASVS defines three verification levels: Level 1 is a low assurance level that is completely penetration testable, Level 2 is for applications containing sensitive data and is the recommended level for most applications, and Level 3 is for the most critical applications such as those handling high value transactions or sensitive medical data (ASVS 4.0.3, Using the ASVS). For a per-change checklist, default to Level 1 items and escalate to Level 2 when the change touches credential storage or session token issuance. That default is a scoping convention of this skill, not an ASVS rule.
Classify each changed file by path first, then confirm or correct with content. A file can belong to more than one surface.
| Surface | Path signals | Content signals |
|---|---|---|
| Authentication | auth/, login/, oauth/, sso/, mfa/, token/ | Password hashing, session creation, JWT issuance, credential validation |
| Session management | session/, cookie, middleware/ | Cookie attribute setting, token expiry, invalidation on logout |
| Input handling | routes/, controllers/, validators/, forms/, parsers/ | SQL queries, template rendering, shell invocation, XML or JSON parsing |
| File upload | upload/, storage/, media/, attachments/ | Multipart handling, MIME validation, storage path construction |
| Deserialization | serializ, marshal, pickle, yaml.load, JSON.parse | Object hydration from an untrusted source |
| Access control | permissions/, policy/, roles/, authz/, acl/ | Role checks, ownership assertions, resource-level guards |
| API and web service | api/, graphql/, soap/, rest/ | Schema validation, HTTP method checks, rate limiting |
| Cryptography | crypto/, cipher, hmac, hash, tls/ | Key generation, algorithm selection, IV or nonce handling |
| Data protection | pii/, gdpr/, models/, db/, cache/ | Sensitive fields stored in plaintext, logging of secrets, caching policy |
Two rules keep the classification honest:
utils/ that calls yaml.load is a deserialization surface; a file under
crypto/ that only re-exports constants is not a cryptography surface.For each changed file, record the surface or surfaces it matched and the count of changed lines
attributed to each. A surface is active when at least one changed line lands in it. Keep the
file list per surface: it is what makes the test items concrete later ("SQL injection probes on
the two new query parameters in orders_controller", not "test for SQL injection"). Record the
excluded surfaces explicitly too. A reader needs to see that file upload was considered and
found untouched, otherwise they cannot tell whether it was skipped or forgotten.
| Surface | ASVS 4.0.3 chapter | Requirement areas to pull items from |
|---|---|---|
| Authentication | V2 Authentication | V2.2 General Authenticator Security, V2.4 Credential Storage, V2.5 Credential Recovery (V2) |
| Session management | V3 Session Management | V3.2 Session Binding, V3.3 Session Termination, V3.4 Cookie-based Session Management (V3) |
| Input handling | V5 Validation, Sanitization and Encoding | V5.1 Input Validation, V5.2 Sanitization and Sandboxing, V5.3 Output Encoding and Injection Prevention (V5) |
| File upload | V12 Files and Resources | V12.1 File Upload, V12.2 File Integrity, V12.3 File Execution, V12.4 File Storage, V12.6 SSRF Protection (V12) |
| Deserialization | V5 Validation, Sanitization and Encoding | V5.5 Deserialization Prevention (V5) |
| Access control | V4 Access Control | V4.1 General Access Control Design, V4.2 Operation Level Access Control, V4.3 Other Access Control Considerations (V4) |
| API and web service | V13 API and Web Service | V13.1 Generic Web Service Security, V13.2 RESTful Web Service, V13.4 GraphQL (V13) |
| Cryptography | V6 Stored Cryptography | V6.2 Algorithms, V6.3 Random Values, V6.4 Secret Management (V6) |
| Data protection | V8 Data Protection, plus V7 Error Handling and Logging | V8.1 General Data Protection, V8.2 Client-side Data Protection, V8.3 Sensitive Private Data (V8); V7.1 Log Content (V7) |
Data protection spans two chapters on purpose. Secrets leaking into logs is a logging requirement (V7.1), not a data protection one, and a checklist that only reads V8 misses it.
| Surface | OWASP Top 10 2021 | WSTG section |
|---|---|---|
| Authentication | A07:2021 Identification and Authentication Failures | 4.4 Authentication Testing |
| Session management | A07:2021 | 4.6 Session Management Testing |
| Input handling | A03:2021 Injection | 4.7 Input Validation Testing |
| File upload | A04:2021 Insecure Design, A10:2021 SSRF | 4.10 Business Logic Testing (4.10.8, 4.10.9) |
| Deserialization | A08:2021 Software and Data Integrity Failures | 4.7 Input Validation Testing (4.7.11 Code Injection) |
| Access control | A01:2021 Broken Access Control | 4.5 Authorization Testing |
| API and web service | A01:2021, A03:2021 | 4.12 API Testing (4.12.1 Testing GraphQL) |
| Cryptography | A02:2021 Cryptographic Failures | 4.9 Testing for Weak Cryptography |
| Data protection | A02:2021, A05:2021 Security Misconfiguration | 4.2 Configuration and Deployment Management Testing |
Three tagging notes that catch people out:
WSTG-<CAT>-<NN> shorthand IDs are not printed on the stable index pages. The section
numbers used here (4.4.3, 4.5.4, and so on) are what the stable guide publishes, so they are
the citable form.Pull only the sections whose surface is active. Rewrite each item with the specific files, parameters, and endpoints recorded in Step 1.
Manual:
Automated:
The remaining eight surfaces (session management, input handling, file upload, deserialization, access control, API and web service, cryptography, data protection) follow the same Manual / Automated shape with their own ASVS 4.0.3, Top 10 2021, and WSTG citations. Pull the full catalog from references/per-surface-test-items.md.
Emit one Markdown block containing, in order:
[MANUAL] or [AUTO], each carrying its
ASVS 4.0.3 requirement ID and, where one applies, its WSTG section number. Name the actual
files, parameters, or endpoints.Keep item 7 even when it feels redundant. It is what stops a green checklist from being read as a sign-off.
Change set: a pull request on a document management service adding shared-link downloads. Changed files:
src/api/routes/share_links.py +142
src/services/share_link_service.py +96
src/storage/attachment_fetcher.py +54
src/models/share_link.py +31
migrations/0042_share_link.sql +18
tests/api/test_share_links.py +210Classification: api/routes/ and the new query parameters make input handling and API and
web service active. storage/ plus a fetch by URL makes file upload active (its SSRF
sub-area specifically). The model and migration add a token column, making data protection
active. share_link tokens are generated in the service, making cryptography active. The
link grants object access without a session, making access control active. No login, cookie,
or deserialization code changed. Test files are excluded from classification.
## Security test plan - docs-service PR #814 - 3f9a1c2
**Surfaces touched:** input handling (142), API and web service (142),
access control (96), file upload / SSRF (54), data protection (49),
cryptography (96)
**ASVS target level:** L2 (the change issues a bearer-style access token)
**Produced:** 2026-07-19
### Input handling
- [ ] [MANUAL] SQL metacharacters on `?token=` and `?expires=` in `share_links.py`; confirm parameterized queries (ASVS 4.0.3 5.3.4; WSTG 4.7.5)
- [ ] [MANUAL] Positive allow-list validation on both new parameters (ASVS 4.0.3 5.1.3)
- [ ] [AUTO] Injection static-analysis rules scoped to `src/api/routes/`
### API and web service
- [ ] [MANUAL] Verb tampering on `/share/{id}`: PUT, DELETE, PATCH (ASVS 4.0.3 13.2.1; WSTG 4.7.3)
- [ ] [MANUAL] Wrong and missing `Content-Type` rejected (ASVS 4.0.3 13.2.5, 13.1.5)
- [ ] [MANUAL] `token` is not exposed in the URL path or logs (ASVS 4.0.3 13.1.3)
### Access control
- [ ] [MANUAL] Fetch another tenant's document id with a valid token (ASVS 4.0.3 4.2.1; WSTG 4.5.4)
- [ ] [MANUAL] Force an exception in the token guard; confirm deny (ASVS 4.0.3 4.1.5)
### File upload / SSRF
- [ ] [MANUAL] `attachment_fetcher.py` remote fetch against 169.254.169.254 and file:// ; confirm allow list (ASVS 4.0.3 12.6.1; A10:2021)
### Cryptography
- [ ] [MANUAL] Token generated via CSPRNG, not `random` (ASVS 4.0.3 6.3.1)
- [ ] [AUTO] Flag `Math.random` / `random.random` in `share_link_service.py`
### Data protection
- [ ] [MANUAL] Token column encrypted or stored hashed (ASVS 4.0.3 8.3.7)
- [ ] [MANUAL] No token value in the new log lines (ASVS 4.0.3 7.1.1)
### Surfaces excluded (no changed lines)
Authentication, session management, deserialization
### Findings already visible in the change
- `share_link_service.py:41` builds the token with `random.randint`. This is a defect now, not a test item. Route it to defect triage.
### Not established by this checklist
Completing these items is evidence that the listed tests ran against this change. It is not a statement that the change is secure, and it is not an ASVS L2 attestation.| Anti-pattern | Why it fails | Correct behavior |
|---|---|---|
| Applying the generic Top 10 list unchanged | Every change gets the same forty items and the team stops reading them | Filter to active surfaces in Step 1 and list the excluded ones explicitly |
| Expanding to a full application assessment | The checklist balloons past what anyone will execute, so nothing gets tested | Bound the plan by the changed surface. A file upload change does not trigger a full authentication review |
| Building the checklist from scanner output | That is triage of findings that already exist, a different input and a different decision | Build this before scanners run; feed findings to defect triage instead |
| Inventing ASVS requirement numbers | Fabricated IDs misroute the tester and destroy trust in every other ID on the page | Cite only IDs read from the published chapter; when unsure, name the chapter and section instead |
| Quoting requirement IDs without a version | ASVS renumbers across major versions, so a bare V2.4 is ambiguous | Write the version next to the ID, as in ASVS 4.0.3 2.4.3 |
| Marking an item PASS with no evidence | Produces false confidence that survives into release | Items are binary: tested with recorded evidence, or not tested |
| Burying an obvious defect as a checklist item | A hard-coded key becomes a task someone might do next sprint | Split it out as a finding in its own section and route it now |
| Treating a complete checklist as a security sign-off | The checklist covers the changed surface only, at one ASVS level | Keep the "not established by this checklist" line in the output |
[AUTO] items are specifications of what to run.
Something else has to run them.WSTG-<CAT>-<NN> identifiers, so section numbers are what this skill cites.Every requirement ID, section number, and quoted phrase above carries its source link at the point it is used. These are the three roots those links come from, for anyone who wants to browse rather than verify one claim:
ASVS 4.0.3 <n.n.n> ID here.4.x.y number.