security-mcp 1.1.4 → 1.3.3
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 +341 -1018
- 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/cloud-controls/aws.json +10712 -0
- package/defaults/cloud-controls/azure.json +7201 -0
- package/defaults/cloud-controls/gcp.json +4061 -0
- package/defaults/control-catalog.json +24 -0
- package/defaults/security-policy.json +2 -2
- package/dist/ci/pr-gate.js +22 -5
- package/dist/cli/index.js +73 -2
- package/dist/cli/install.js +4 -55
- package/dist/cli/onboarding.js +18 -10
- package/dist/gate/baseline.js +82 -7
- package/dist/gate/catalog.js +10 -2
- package/dist/gate/checks/agentic-instructions.js +515 -0
- package/dist/gate/checks/ai-governance.js +132 -0
- 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/cloud-controls.js +69 -0
- package/dist/gate/checks/crypto.js +423 -2
- package/dist/gate/checks/data-platform.js +954 -0
- package/dist/gate/checks/dependencies.js +582 -15
- package/dist/gate/checks/docker-deep.js +1236 -0
- package/dist/gate/checks/gitops.js +724 -0
- package/dist/gate/checks/graphql.js +201 -19
- package/dist/gate/checks/iac.js +1230 -0
- package/dist/gate/checks/infra.js +246 -1
- package/dist/gate/checks/injection-deep.js +827 -184
- package/dist/gate/checks/k8s.js +955 -2
- 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 +256 -13
- package/dist/gate/checks/supply-chain-deep.js +787 -0
- package/dist/gate/checks/web-nextjs.js +572 -48
- package/dist/gate/cloud-controls/apply.js +115 -0
- package/dist/gate/cloud-controls/bicep.js +36 -0
- package/dist/gate/cloud-controls/cfn.js +125 -0
- package/dist/gate/cloud-controls/detect.js +104 -0
- package/dist/gate/cloud-controls/hcl.js +140 -0
- package/dist/gate/cloud-controls/types.js +87 -0
- package/dist/gate/diff.js +17 -5
- package/dist/gate/evidence.js +8 -1
- package/dist/gate/exceptions.js +202 -9
- package/dist/gate/findings.js +15 -2
- package/dist/gate/policy.js +316 -130
- package/dist/gate/threat-intel.js +6 -0
- package/dist/mcp/audit-chain.js +131 -28
- package/dist/mcp/auth.js +169 -0
- package/dist/mcp/learning.js +129 -4
- package/dist/mcp/model-router.js +161 -24
- package/dist/mcp/orchestration.js +377 -89
- package/dist/mcp/server.js +460 -69
- package/dist/mcp/tool-audit.js +193 -0
- package/dist/repo/fs.js +37 -1
- package/dist/repo/search.js +31 -6
- package/dist/review/store.js +56 -3
- package/dist/tests/run.js +124 -1
- package/package.json +9 -9
- package/skills/_TEMPLATE/SKILL.md +99 -0
- package/skills/advanced-dos-tester/SKILL.md +118 -0
- package/skills/agentic-instruction-auditor/SKILL.md +111 -0
- package/skills/agentic-loop-exploiter/SKILL.md +377 -0
- package/skills/ai-llm-redteam/SKILL.md +113 -0
- package/skills/ai-model-supply-chain-agent/SKILL.md +112 -0
- package/skills/algorithm-implementation-reviewer/SKILL.md +107 -0
- package/skills/android-penetration-tester/SKILL.md +464 -46
- package/skills/anti-replay-tester/SKILL.md +115 -0
- package/skills/appsec-code-auditor/SKILL.md +94 -0
- package/skills/artifact-integrity-analyst/SKILL.md +450 -0
- package/skills/attack-navigator/SKILL.md +476 -8
- package/skills/auth-session-hacker/SKILL.md +111 -0
- package/skills/aws-penetration-tester/SKILL.md +510 -0
- package/skills/azure-penetration-tester/SKILL.md +542 -3
- package/skills/binary-auth-validator/SKILL.md +120 -0
- package/skills/bot-detection-specialist/SKILL.md +118 -0
- package/skills/business-logic-attacker/SKILL.md +240 -0
- package/skills/capec-code-mapper/SKILL.md +93 -0
- package/skills/cert-pin-rotation-specialist/SKILL.md +121 -0
- package/skills/cicd-pipeline-hijacker/SKILL.md +414 -0
- package/skills/ciso-orchestrator/SKILL.md +465 -43
- package/skills/cloud-infra-specialist/SKILL.md +127 -0
- package/skills/compliance-gap-analyst/SKILL.md +431 -0
- package/skills/compliance-grc/SKILL.md +94 -0
- package/skills/compliance-lifecycle-tracker/SKILL.md +93 -0
- package/skills/container-hardening-auditor/SKILL.md +125 -0
- package/skills/credential-stuffing-specialist/SKILL.md +111 -0
- package/skills/crypto-pki-specialist/SKILL.md +96 -0
- package/skills/csa-ccm-mapper/SKILL.md +93 -0
- package/skills/csf2-governance-mapper/SKILL.md +93 -0
- package/skills/data-platform-auditor/SKILL.md +125 -0
- package/skills/deep-link-fuzzer/SKILL.md +118 -0
- package/skills/dependency-confusion-attacker/SKILL.md +424 -0
- package/skills/device-integrity-aggregator/SKILL.md +117 -0
- package/skills/dos-resilience-tester/SKILL.md +106 -0
- package/skills/dread-scorer/SKILL.md +93 -0
- package/skills/egress-policy-enforcer/SKILL.md +108 -0
- package/skills/evidence-collector/SKILL.md +107 -0
- package/skills/file-upload-attacker/SKILL.md +118 -0
- package/skills/gcp-penetration-tester/SKILL.md +510 -2
- package/skills/git-history-secret-scanner/SKILL.md +115 -0
- package/skills/gitops-delivery-auditor/SKILL.md +120 -0
- package/skills/iac-security-auditor/SKILL.md +125 -0
- package/skills/iam-privesc-graph-builder/SKILL.md +161 -0
- package/skills/incident-responder/SKILL.md +120 -0
- package/skills/injection-specialist/SKILL.md +111 -0
- package/skills/ios-security-auditor/SKILL.md +291 -0
- package/skills/json-ambiguity-tester/SKILL.md +145 -0
- package/skills/k8s-container-escaper/SKILL.md +406 -0
- package/skills/key-management-lifecycle-analyst/SKILL.md +107 -0
- package/skills/kill-switch-engineer/SKILL.md +111 -0
- package/skills/linddun-privacy-analyst/SKILL.md +111 -0
- package/skills/logic-race-fuzzer/SKILL.md +452 -0
- package/skills/mobile-api-network-attacker/SKILL.md +430 -0
- package/skills/mobile-binary-hardener/SKILL.md +111 -0
- package/skills/mobile-security-specialist/SKILL.md +94 -0
- package/skills/mobile-webview-auditor/SKILL.md +105 -0
- package/skills/model-extraction-attacker/SKILL.md +228 -0
- package/skills/multipart-abuse-tester/SKILL.md +93 -0
- package/skills/oauth-pkce-specialist/SKILL.md +113 -0
- package/skills/parser-exhaustion-tester/SKILL.md +151 -0
- package/skills/pentest-infra/SKILL.md +107 -0
- package/skills/pentest-social/SKILL.md +210 -0
- package/skills/pentest-team/SKILL.md +96 -0
- package/skills/pentest-web-api/SKILL.md +107 -0
- package/skills/privacy-flow-analyst/SKILL.md +243 -0
- package/skills/prompt-injection-specialist/SKILL.md +403 -0
- package/skills/quantum-migration-planner/SKILL.md +105 -0
- package/skills/rag-poisoning-specialist/SKILL.md +367 -0
- package/skills/registry-mirror-enforcer/SKILL.md +93 -0
- package/skills/rotation-validation-agent/SKILL.md +121 -0
- package/skills/samm-assessor/SKILL.md +94 -0
- package/skills/secrets-mask-bypass-tester/SKILL.md +109 -0
- package/skills/senior-security-engineer/SKILL.md +178 -0
- package/skills/serialization-memory-attacker/SKILL.md +341 -0
- package/skills/session-timeout-tester/SKILL.md +170 -0
- package/skills/slsa-level3-enforcer/SKILL.md +121 -0
- package/skills/slsa-provenance-enforcer/SKILL.md +111 -0
- package/skills/ssrf-detection-validator/SKILL.md +117 -0
- package/skills/step-up-auth-enforcer/SKILL.md +93 -0
- package/skills/stride-pasta-analyst/SKILL.md +429 -0
- package/skills/supply-chain-devsecops/SKILL.md +107 -0
- package/skills/threat-infrastructure-analyst/SKILL.md +93 -0
- package/skills/threat-modeler/SKILL.md +94 -0
- package/skills/tls-certificate-auditor/SKILL.md +582 -18
- package/skills/token-reuse-detector/SKILL.md +104 -0
- package/skills/trike-risk-modeler/SKILL.md +93 -0
- package/skills/unicode-homograph-tester/SKILL.md +93 -0
- package/skills/waf-rule-lifecycle-agent/SKILL.md +106 -0
- package/skills/webhook-security-tester/SKILL.md +111 -0
- package/skills/zero-trust-architect/SKILL.md +118 -0
|
@@ -22,6 +22,15 @@ Audit every dependency for: confusion attacks, typosquatting, known CVEs, CISA K
|
|
|
22
22
|
abandoned packages, and missing integrity verification. Generate an SBOM. Write fixes to
|
|
23
23
|
lockfiles and package.json.
|
|
24
24
|
|
|
25
|
+
## BEYOND THE CHECKS — AUTONOMOUS DETECT & FIX
|
|
26
|
+
|
|
27
|
+
The `dependencies` + `supply-chain-deep` + `sbom` detection modules (`src/gate/checks/dependencies.ts`, `src/gate/checks/supply-chain-deep.ts`, `src/gate/checks/sbom.ts`) are your deterministic floor, not your ceiling. Treat their finding IDs as the minimum, then reason past single-line/single-file pattern matching — and APPLY the fix (Edit), not just advise:
|
|
28
|
+
|
|
29
|
+
- **Cross-file / data-flow reasoning the regex can't do:** correlate an unscoped name in `package.json`, the registry-priority ordering in `.npmrc`, and the actual lockfile `resolved` URL together — confusion only exists when all three line up; no single-file rule sees that.
|
|
30
|
+
- **Semantic / effective-state analysis:** build the full direct+transitive dependency tree, then model whether a higher public version would win semver resolution over the intended private package; diff the tarball's extracted `package.json` against the registry metadata (manifest confusion); follow lifecycle-script taint (`postinstall` → network sink).
|
|
31
|
+
- **External corroboration:** WebSearch/WebFetch for the current CISA KEV catalog, OSV.dev advisories, and npm/PyPI publish dates to catch AI-hallucination-squatting and abandoned packages.
|
|
32
|
+
- **Apply & prove:** write the fix inline (scope the name, pin `.npmrc`, add SHA-512 integrity, SHA-pin GitHub Actions), re-run the `dependencies`/`supply-chain-deep`/`sbom` checks plus `osv-scanner` and `cyclonedx-bom validate` as a regression floor, then re-audit. Emit the LEARNING SIGNAL per fix; surface trade-offs with the secure default.
|
|
33
|
+
|
|
25
34
|
## EXECUTION
|
|
26
35
|
|
|
27
36
|
1. Read all package manifests: `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`,
|
|
@@ -76,3 +85,418 @@ If internet permitted:
|
|
|
76
85
|
- Package name, current version, vulnerability ID, CVSSv4, EPSS, CISA KEV status, fix version
|
|
77
86
|
- Whether fix has been applied to lockfile
|
|
78
87
|
SBOM written to `.mcp/agent-runs/{agentRunId}/sbom.cyclonedx.json`
|
|
88
|
+
|
|
89
|
+
Every findings JSON MUST include `intelligenceForOtherAgents`:
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"intelligenceForOtherAgents": {
|
|
93
|
+
"forPentestTeam": [{ "type": "HIGH_VALUE_TARGET", "description": "...", "exploitHint": "..." }],
|
|
94
|
+
"forCryptoSpecialist": [{ "type": "CRYPTO_WEAKNESS_REFERENCE", "algorithm": "...", "location": "..." }],
|
|
95
|
+
"forCloudSpecialist": [{ "type": "SSRF_TO_CLOUD_CHAIN", "ssrfLocation": "...", "escalationPath": "..." }],
|
|
96
|
+
"forComplianceGrc": [{ "type": "COMPLIANCE_BLOCKER", "frameworks": ["..."], "releaseBlock": true }]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## BEYOND SKILL.MD — MANDATORY EXPANSIONS
|
|
104
|
+
|
|
105
|
+
These six domain-specific expansions go beyond the base mandate. Each must be executed on
|
|
106
|
+
every run — they are not optional enrichment.
|
|
107
|
+
|
|
108
|
+
### 1. Manifest Confusion Attack (CVE-2023-35116 class)
|
|
109
|
+
|
|
110
|
+
**Technique:** Attackers craft packages where the `package.json` presented to the registry
|
|
111
|
+
differs from the one extracted by npm install. The registry reads a top-level `package.json`
|
|
112
|
+
while npm resolves a nested or overridden one inside a tarball's subdirectory. This allows
|
|
113
|
+
hiding malicious `postinstall` scripts or dependency overrides from registry-level scanners.
|
|
114
|
+
|
|
115
|
+
**Detection:** For every package tarball in the lockfile, verify that the `_id` and `scripts`
|
|
116
|
+
fields in the registry's published metadata match what is extracted to `node_modules/<pkg>/package.json`
|
|
117
|
+
on disk after install. Run:
|
|
118
|
+
```bash
|
|
119
|
+
npm pack <package>@<version> --dry-run 2>&1 | grep -E "package.json"
|
|
120
|
+
tar -tzf $(npm pack <package>@<version> 2>/dev/null) | grep package.json
|
|
121
|
+
```
|
|
122
|
+
Finding: more than one `package.json` in the tarball root, or a `package.json` that is not
|
|
123
|
+
at the tarball root, is a manifest confusion candidate.
|
|
124
|
+
|
|
125
|
+
### 2. GitHub Actions Supply Chain Injection (SLSA Level 0 Gap)
|
|
126
|
+
|
|
127
|
+
**Technique:** CI pipelines that reference actions via floating tags (`uses: actions/checkout@v3`)
|
|
128
|
+
rather than pinned SHA commits are vulnerable to tag-moving attacks. Maintainer account
|
|
129
|
+
compromise, typosquatted action names (`actions/chekout`), or malicious forks pushed under
|
|
130
|
+
a hijacked org all achieve arbitrary code execution in the CI build environment — where
|
|
131
|
+
secrets, tokens, and cloud credentials are present.
|
|
132
|
+
|
|
133
|
+
**Detection:** Grep all `.github/workflows/*.yml` for `uses:` lines not pinned to a full
|
|
134
|
+
40-character SHA:
|
|
135
|
+
```bash
|
|
136
|
+
grep -rn "uses:" .github/workflows/ | grep -v "@[0-9a-f]\{40\}"
|
|
137
|
+
```
|
|
138
|
+
Every non-SHA pin is a finding. Cross-reference action names against the `step-security/harden-runner`
|
|
139
|
+
known-bad-actions list. Finding: any floating-tag action reference = HIGH. Any action name
|
|
140
|
+
with Levenshtein distance ≤ 1 from a known legitimate action = CRITICAL.
|
|
141
|
+
|
|
142
|
+
### 3. Dependency Confusion via Internal Package Registry Priority Inversion
|
|
143
|
+
|
|
144
|
+
**Technique:** Private registries configured with `registry=https://private.registry/` in
|
|
145
|
+
`.npmrc` alongside `@scope:registry=https://private.registry/` can still resolve unscoped
|
|
146
|
+
packages from the public registry if the private registry returns a 404 for those names.
|
|
147
|
+
An attacker who discovers an internal unscoped package name (via job listings, error messages,
|
|
148
|
+
open-source leaks, or OSINT) can publish a higher-versioned package to public npm, causing
|
|
149
|
+
npm to prefer it via semver resolution even when a private copy exists.
|
|
150
|
+
|
|
151
|
+
**Detection:**
|
|
152
|
+
```bash
|
|
153
|
+
# Extract all unscoped dependencies
|
|
154
|
+
node -e "const p=require('./package.json'); console.log(Object.keys({...p.dependencies,...p.devDependencies}).filter(n=>!n.startsWith('@')))"
|
|
155
|
+
# For each, check if it exists on public npm
|
|
156
|
+
for pkg in <unscoped-list>; do curl -sf "https://registry.npmjs.org/$pkg" | jq '.name' ; done
|
|
157
|
+
```
|
|
158
|
+
Finding: any unscoped private package name that resolves successfully on public npm = CRITICAL
|
|
159
|
+
dependency confusion surface.
|
|
160
|
+
|
|
161
|
+
### 4. PyPI Dependency Confusion and Wheel Filename Spoofing
|
|
162
|
+
|
|
163
|
+
**Technique:** PyPI package names are normalised (hyphens and underscores are interchangeable,
|
|
164
|
+
case-insensitive). A private package named `my_internal_lib` can be confused with
|
|
165
|
+
`my-internal-lib` or `My_Internal_Lib` published to PyPI. Additionally, malicious wheel
|
|
166
|
+
files can be crafted with platform tags that cause pip to prefer them on specific OS/arch
|
|
167
|
+
combinations while the safe version is served on the CI platform.
|
|
168
|
+
|
|
169
|
+
**Detection:**
|
|
170
|
+
```bash
|
|
171
|
+
# Normalise all requirement names and check PyPI
|
|
172
|
+
pip index versions <package> 2>/dev/null | head -1
|
|
173
|
+
# Check for wheel platform confusion
|
|
174
|
+
pip download <package> --no-deps --dest /tmp/wheels/ && ls /tmp/wheels/
|
|
175
|
+
```
|
|
176
|
+
Finding: any `requirements.txt` package resolvable on PyPI whose PyPI maintainer differs from
|
|
177
|
+
the expected internal team = HIGH. Wheel files with unexpected platform tags in lockfiles = MEDIUM.
|
|
178
|
+
|
|
179
|
+
### 5. AI-Assisted Dependency Hallucination Attack (Emerging — Post-2024)
|
|
180
|
+
|
|
181
|
+
**Technique:** LLM coding assistants (GitHub Copilot, Cursor, Claude, GPT-4) hallucinate
|
|
182
|
+
package names that do not exist on public registries. Attackers monitor common hallucination
|
|
183
|
+
patterns (e.g., `express-validator-middleware`, `react-auth-helper`) and pre-register those
|
|
184
|
+
names on npm/PyPI. When a developer installs the hallucinated name based on an AI suggestion,
|
|
185
|
+
they install the attacker's package. This attack class requires no typosquatting — the package
|
|
186
|
+
name is invented from scratch by the AI.
|
|
187
|
+
|
|
188
|
+
**Detection:** For every dependency added in the last 6 months (check git log on package.json),
|
|
189
|
+
verify the package existed on the public registry before the date it was added to package.json:
|
|
190
|
+
```bash
|
|
191
|
+
git log --follow -p package.json | grep '^\+' | grep '"name-to-check"'
|
|
192
|
+
# Cross with npm publish date: curl https://registry.npmjs.org/<pkg> | jq '.time.created'
|
|
193
|
+
```
|
|
194
|
+
Finding: a package whose first publish date on the public registry is within 30 days of
|
|
195
|
+
its addition to the project's package.json, and which has <100 weekly downloads = HIGH
|
|
196
|
+
AI-hallucination-squatting candidate.
|
|
197
|
+
|
|
198
|
+
### 6. SLSA Provenance and Build Attestation Gaps (US EO 14028 / EU CRA)
|
|
199
|
+
|
|
200
|
+
**Technique:** Without SLSA build provenance attestations, the build artifact cannot be
|
|
201
|
+
cryptographically linked to the source commit that produced it. An attacker who compromises
|
|
202
|
+
a build server can substitute a malicious artifact after the source checkout step, and
|
|
203
|
+
downstream consumers have no way to detect the substitution. This applies to npm packages,
|
|
204
|
+
container images, and Go modules alike.
|
|
205
|
+
|
|
206
|
+
**Detection:** For each published package or container in this project:
|
|
207
|
+
```bash
|
|
208
|
+
# Check for SLSA provenance attestation
|
|
209
|
+
gh attestation verify <artifact> --owner <org>
|
|
210
|
+
# Check npm package for provenance
|
|
211
|
+
npm audit signatures <package>@<version>
|
|
212
|
+
# Check for sigstore signatures
|
|
213
|
+
cosign verify <image>:<tag> --certificate-oidc-issuer https://token.actions.githubusercontent.com
|
|
214
|
+
```
|
|
215
|
+
Finding: any artifact published from CI without a verifiable SLSA L2+ provenance attestation
|
|
216
|
+
= HIGH. Any container image without a cosign signature from a trusted OIDC issuer = HIGH.
|
|
217
|
+
For projects subject to US EO 14028 or EU CRA: unsigned artifacts = CRITICAL compliance blocker.
|
|
218
|
+
|
|
219
|
+
### 7. Go Module Proxy Cache Poisoning and Replace Directive Abuse
|
|
220
|
+
|
|
221
|
+
**Technique:** Go's module proxy (proxy.golang.org) caches module zip files. If an attacker
|
|
222
|
+
publishes a malicious module before the legitimate maintainer has claimed the module path,
|
|
223
|
+
the proxy serves the malicious version to all subsequent downloads. Additionally, `replace`
|
|
224
|
+
directives in `go.mod` that point to relative local paths or unverified GitHub forks
|
|
225
|
+
introduce dependency substitution that is invisible to standard SCA tools.
|
|
226
|
+
|
|
227
|
+
**Detection:**
|
|
228
|
+
```bash
|
|
229
|
+
grep -n "replace" go.mod
|
|
230
|
+
# For each replace directive, verify the target
|
|
231
|
+
# Local path replaces: acceptable only in development, NEVER in published modules
|
|
232
|
+
grep -A1 "^replace" go.mod | grep -v "=>" | grep -v "^--$"
|
|
233
|
+
# Check GOPROXY for each dependency
|
|
234
|
+
GOPROXY=direct go mod download -json ./... 2>&1 | jq '.Path,.Version,.Dir'
|
|
235
|
+
```
|
|
236
|
+
Finding: any `replace` directive pointing to a local path in a production go.mod = HIGH.
|
|
237
|
+
Any `replace` directive pointing to a GitHub fork without a `go.sum` entry = CRITICAL.
|
|
238
|
+
|
|
239
|
+
### 8. Transitive Dependency Shadow and Phantom Dependency Exploitation
|
|
240
|
+
|
|
241
|
+
**Technique:** Build tools that hoist transitive dependencies to the root `node_modules`
|
|
242
|
+
(npm v3+, Yarn v1 hoisting) allow application code to `require()` packages that are not
|
|
243
|
+
declared in the project's own `package.json`. These "phantom dependencies" can be exploited
|
|
244
|
+
by introducing a malicious package that has the same name as a hoisted transitive dependency
|
|
245
|
+
at a higher version — causing the malicious version to be resolved first. pnpm's strict
|
|
246
|
+
mode prevents hoisting but is frequently disabled via `public-hoist-pattern=*`.
|
|
247
|
+
|
|
248
|
+
**Detection:**
|
|
249
|
+
```bash
|
|
250
|
+
# Find phantom dependencies (imported but not declared)
|
|
251
|
+
node -e "
|
|
252
|
+
const declared = new Set(Object.keys(require('./package.json').dependencies || {}));
|
|
253
|
+
const fs = require('fs');
|
|
254
|
+
// grep all source imports
|
|
255
|
+
"
|
|
256
|
+
# Check pnpm config for disabled strict mode
|
|
257
|
+
grep "public-hoist-pattern" .npmrc pnpm-workspace.yaml 2>/dev/null
|
|
258
|
+
```
|
|
259
|
+
Finding: any `require()` or `import` of a package not in `dependencies` or `devDependencies` = MEDIUM.
|
|
260
|
+
`public-hoist-pattern=*` in a pnpm project = HIGH (eliminates pnpm's primary confusion defence).
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## §DEPENDENCY_CONFUSION_ATTACKER-CHECKLIST
|
|
265
|
+
|
|
266
|
+
Perform each item in order. Record the result inline before moving to the next.
|
|
267
|
+
|
|
268
|
+
1. **Unscoped private package name collision** — For every unscoped package in `dependencies`
|
|
269
|
+
and `devDependencies`, query `https://registry.npmjs.org/<name>` and confirm the response
|
|
270
|
+
is 404 or is controlled by the organisation. Any 200 response where the maintainer is not
|
|
271
|
+
the internal team = CRITICAL. Grep: `jq '.dependencies, .devDependencies | keys[]' package.json | grep -v '^@'`
|
|
272
|
+
|
|
273
|
+
2. **Registry priority order in `.npmrc`** — Confirm that `.npmrc` specifies the private
|
|
274
|
+
registry as the default (`registry=`) and that scoped packages are pinned to the private
|
|
275
|
+
registry with `@scope:registry=`. Absence of scope-pinning with a private registry configured
|
|
276
|
+
= HIGH. Grep: `cat .npmrc | grep -E "registry|scope"`
|
|
277
|
+
|
|
278
|
+
3. **Lockfile integrity hash coverage** — Every entry in `package-lock.json` must have an
|
|
279
|
+
`integrity` field with a `sha512-` prefix. Missing or `sha1-` prefixed integrity values
|
|
280
|
+
indicate an old or tampered lockfile. Finding: `jq '.. | .integrity? | select(. != null) | select(startswith("sha1"))' package-lock.json`
|
|
281
|
+
|
|
282
|
+
4. **Postinstall and lifecycle script network calls** — For every package with a `scripts.postinstall`,
|
|
283
|
+
`scripts.install`, `scripts.prepare`, or `scripts.preinstall` field, confirm the script
|
|
284
|
+
does not contain `curl`, `wget`, `fetch`, `http`, `https`, or `require('http')`. Any
|
|
285
|
+
network call in a lifecycle script = HIGH. Grep: `find node_modules -name package.json -maxdepth 3 | xargs grep -l "postinstall\|install\|prepare" | xargs grep -l "curl\|wget\|http"`
|
|
286
|
+
|
|
287
|
+
5. **GitHub Actions floating tag pins** — All `uses:` references in `.github/workflows/` must
|
|
288
|
+
be pinned to a 40-character SHA. Floating tags (`@v1`, `@main`, `@latest`) = HIGH per
|
|
289
|
+
reference. Finding threshold: any unresolved floating tag. Grep: `grep -rn "uses:" .github/workflows/ | grep -v "@[0-9a-f]\{40\}"`
|
|
290
|
+
|
|
291
|
+
6. **Go module replace directive audit** — Every `replace` directive in `go.mod` must reference
|
|
292
|
+
a published, version-tagged module or a workspace-local path that is explicitly declared
|
|
293
|
+
in `go.work`. Replace directives pointing to arbitrary GitHub branches = CRITICAL.
|
|
294
|
+
Grep: `grep -n "replace" go.mod`
|
|
295
|
+
|
|
296
|
+
7. **Python hash pinning** — Every `requirements.txt` and `Pipfile.lock` must include SHA-256
|
|
297
|
+
hashes for each package. Absence of `--hash=sha256:` in requirements files = HIGH.
|
|
298
|
+
Finding: `grep -rL "hash" requirements*.txt 2>/dev/null`
|
|
299
|
+
|
|
300
|
+
8. **SLSA attestation presence** — Run `npm audit signatures` for all production npm packages.
|
|
301
|
+
Run `gh attestation verify` for any GitHub-published artifacts. Absence of provenance
|
|
302
|
+
for packages published from this project's CI = HIGH. Finding: any package with
|
|
303
|
+
`missing` signature status in `npm audit signatures` output.
|
|
304
|
+
|
|
305
|
+
9. **Abandoned and deprecated package detection** — For the top 20 production dependencies
|
|
306
|
+
by download count, check the npm registry `time` field for last publish date. Any package
|
|
307
|
+
with no publish in >730 days and >100 dependents = MEDIUM. Any package flagged `deprecated`
|
|
308
|
+
in registry metadata = HIGH. Check: `curl https://registry.npmjs.org/<pkg> | jq '.time | keys | last'`
|
|
309
|
+
|
|
310
|
+
10. **Typosquatting Levenshtein scan** — Compute Levenshtein distance between each dependency
|
|
311
|
+
name and the top-1000 npm/PyPI packages. Distance ≤ 1 = CRITICAL. Distance = 2 with
|
|
312
|
+
>10K weekly downloads on the target = HIGH. Finding: report the pair `(project_dep, popular_pkg, distance)`.
|
|
313
|
+
|
|
314
|
+
11. **AI hallucination squatting** — For every dependency added in the past 6 months, verify
|
|
315
|
+
the package publish date predates its addition to `package.json` by at least 30 days
|
|
316
|
+
AND the package has >1000 weekly downloads (indicating it is a known, established package).
|
|
317
|
+
Packages that fail both checks = HIGH. Check: cross `git log package.json` with
|
|
318
|
+
`curl https://registry.npmjs.org/<pkg> | jq '.time.created'`
|
|
319
|
+
|
|
320
|
+
12. **CycloneDX SBOM completeness** — The generated SBOM must include all direct AND transitive
|
|
321
|
+
dependencies with PURL, license, and hash fields populated. Any component missing a PURL
|
|
322
|
+
or hash = MEDIUM SBOM quality gap. Verify with:
|
|
323
|
+
`cyclonedx-bom validate --input-format json sbom.cyclonedx.json`
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## §POC-REQUIREMENT
|
|
328
|
+
|
|
329
|
+
For every CRITICAL or HIGH finding in this domain, the following sequence is MANDATORY.
|
|
330
|
+
Skipping any step downgrades the finding severity to MEDIUM automatically.
|
|
331
|
+
|
|
332
|
+
**Step 1 — Write the working PoC FIRST:**
|
|
333
|
+
Document the exact payload, exact command, or exact registry interaction that demonstrates
|
|
334
|
+
the vulnerability is exploitable. For dependency confusion: show the exact package name,
|
|
335
|
+
registry URL, and version number that would be resolved ahead of the intended private package.
|
|
336
|
+
For typosquatting: show the Levenshtein-adjacent package name and its public npm page.
|
|
337
|
+
For lifecycle script exfiltration: show the exact `postinstall` script content and the
|
|
338
|
+
network destination it would reach.
|
|
339
|
+
|
|
340
|
+
**Step 2 — Confirm reproduction:**
|
|
341
|
+
Execute the PoC in a controlled environment (dry-run install, offline registry simulation,
|
|
342
|
+
or a dedicated test namespace). Capture the output showing the malicious resolution path.
|
|
343
|
+
Record the captured output verbatim.
|
|
344
|
+
|
|
345
|
+
**Step 3 — Write the fix:**
|
|
346
|
+
Apply the specific remediation: scope the package name, pin the registry, add hash integrity,
|
|
347
|
+
remove the malicious script, or add a `no-install-scripts` policy.
|
|
348
|
+
|
|
349
|
+
**Step 4 — Verify PoC fails against fix:**
|
|
350
|
+
Re-run the PoC after applying the fix. Confirm the previously-demonstrated resolution path
|
|
351
|
+
no longer occurs. Capture the output showing the fix is effective.
|
|
352
|
+
|
|
353
|
+
**Step 5 — Record in findings JSON:**
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"findingId": "DEP-CONFUSION-001",
|
|
357
|
+
"severity": "CRITICAL",
|
|
358
|
+
"exploitPoC": {
|
|
359
|
+
"command": "npm install --registry https://registry.npmjs.org my-internal-lib",
|
|
360
|
+
"expectedOutcome": "npm resolves to attacker-controlled v99.0.0 from public registry",
|
|
361
|
+
"observedOutput": "<paste npm install output showing malicious version resolved>",
|
|
362
|
+
"reproduced": true
|
|
363
|
+
},
|
|
364
|
+
"fix": "Rename to @myorg/my-internal-lib and add @myorg:registry= to .npmrc",
|
|
365
|
+
"fixVerified": true,
|
|
366
|
+
"pocFailsAgainstFix": true
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
---
|
|
371
|
+
|
|
372
|
+
## §PROJECT-ESCALATION
|
|
373
|
+
|
|
374
|
+
Immediately call `orchestration.update_agent_status` with flag `"CRITICAL_ESCALATION"` and
|
|
375
|
+
halt normal processing to alert the orchestrator before completing under any of these conditions:
|
|
376
|
+
|
|
377
|
+
1. **CISA KEV match in production dependency** — Any production dependency (direct or transitive
|
|
378
|
+
up to 3 levels deep) matches an entry in the current CISA Known Exploited Vulnerabilities
|
|
379
|
+
catalog. These vulnerabilities have confirmed real-world exploitation; the entire release
|
|
380
|
+
must be blocked until remediated.
|
|
381
|
+
|
|
382
|
+
2. **Malicious postinstall script with live exfiltration target** — A package's lifecycle
|
|
383
|
+
script contains a hardcoded IP address or domain that resolves to a non-CDN, non-registry
|
|
384
|
+
endpoint. This indicates an active supply chain compromise, not a misconfiguration.
|
|
385
|
+
Escalate before attempting to remediate — the incident response team must be notified.
|
|
386
|
+
|
|
387
|
+
3. **Dependency confusion with version higher than internal package** — Public npm already
|
|
388
|
+
has a package with the same unscoped name as a private internal package, at a version
|
|
389
|
+
number higher than the internal package. This means an active confusion attack may already
|
|
390
|
+
be exploitable or actively exploited in CI/CD pipelines.
|
|
391
|
+
|
|
392
|
+
4. **Lockfile tampered or unsigned commit detected** — `package-lock.json` has been modified
|
|
393
|
+
without a corresponding change to `package.json` in the same commit, and the modifying
|
|
394
|
+
commit is not from a known CI bot or maintainer. This pattern is consistent with a lockfile
|
|
395
|
+
poisoning attack (e.g., CVE-2021-43616 class).
|
|
396
|
+
|
|
397
|
+
5. **Go module path hijacking via GONOSUMCHECK or GONOSUMDB** — The project sets `GONOSUMCHECK`
|
|
398
|
+
or `GONOSUMDB` for a module path that is not an internal module. This disables the Go
|
|
399
|
+
checksum database for that module, allowing a substituted malicious version to be
|
|
400
|
+
downloaded without detection.
|
|
401
|
+
|
|
402
|
+
6. **Action name typosquatting in CI** — A `.github/workflows/` file references a GitHub
|
|
403
|
+
Action whose name has Levenshtein distance ≤ 1 from a known legitimate action (e.g.,
|
|
404
|
+
`actions/chekout` vs `actions/checkout`). This is an active supply chain attack vector
|
|
405
|
+
with immediate code execution impact in the CI environment where secrets are present.
|
|
406
|
+
|
|
407
|
+
7. **Phantom SBOM component — dependency present in node_modules but absent from all manifest files** —
|
|
408
|
+
A package directory exists under `node_modules/` with no corresponding entry in any
|
|
409
|
+
`package.json` (project or any workspace). This indicates either a compromised install
|
|
410
|
+
or a phantom inject. Escalate immediately — do not attempt automated remediation.
|
|
411
|
+
|
|
412
|
+
8. **Published package SHA-512 mismatch between lockfile and registry** — The `integrity`
|
|
413
|
+
hash recorded in `package-lock.json` does not match the hash served by the registry for
|
|
414
|
+
the same package version. This is the clearest possible indicator of a compromised package
|
|
415
|
+
or a man-in-the-middle registry attack.
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## §EDGE-CASE-MATRIX
|
|
420
|
+
|
|
421
|
+
The 5 attack cases in this domain that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
|
|
422
|
+
|
|
423
|
+
| # | Edge Case | Why Scanners Miss It | Concrete Test |
|
|
424
|
+
|---|-----------|----------------------|---------------|
|
|
425
|
+
| 1 | Second-order / stored payload executed in different context | Scanner checks input context, not execution context | Store payload safely; trigger in separate request/session |
|
|
426
|
+
| 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 |
|
|
427
|
+
| 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 |
|
|
428
|
+
| 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 |
|
|
429
|
+
| 5 | Race condition between check and use (TOCTOU) | Sequential scanners don't model concurrency | Send two simultaneous requests to the same state-changing endpoint |
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## §TEMPORAL-THREATS
|
|
434
|
+
|
|
435
|
+
Threats materialising in the 2025–2030 window that defences designed today must account for.
|
|
436
|
+
|
|
437
|
+
| Threat | Est. Timeline | Relevance to This Domain | Prepare Now By |
|
|
438
|
+
|--------|--------------|--------------------------|----------------|
|
|
439
|
+
| 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) |
|
|
440
|
+
| 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 |
|
|
441
|
+
| EU AI Act full enforcement | 2026 | High-risk AI systems require mandatory conformity assessments | Classify all AI features against AI Act tiers now |
|
|
442
|
+
| Post-quantum TLS migration deadline | 2028–2030 | Browser vendors will drop classical-only TLS connections | Begin TLS agility assessment; test hybrid key exchange |
|
|
443
|
+
| 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 |
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## §DETECTION-GAP
|
|
448
|
+
|
|
449
|
+
What current security monitoring CANNOT detect in this domain, and what to build to close each gap.
|
|
450
|
+
|
|
451
|
+
**Standard gaps that MUST be checked:**
|
|
452
|
+
|
|
453
|
+
- **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.
|
|
454
|
+
- **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.
|
|
455
|
+
- **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.
|
|
456
|
+
- **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.
|
|
457
|
+
- **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.
|
|
458
|
+
|
|
459
|
+
**Domain-specific detection gaps for dependency-confusion-attacker:**
|
|
460
|
+
|
|
461
|
+
- **Manifest confusion (tarball vs registry metadata mismatch)**: Standard SCA tools read registry metadata, not the extracted tarball content. No tool currently diffs the two automatically. Need: post-install hook that re-computes `package.json` hash from extracted `node_modules/<pkg>/package.json` and compares against registry-published hash.
|
|
462
|
+
- **AI hallucination squatting — new package monitoring**: No existing scanner monitors for packages being registered on public npm/PyPI that match names generated by LLM coding assistants. Need: a custom monitor that alerts when a previously-nonexistent package name appears on a public registry within a configurable window of it being added to `package.json`.
|
|
463
|
+
- **SLSA attestation forgery via compromised OIDC token**: Provenance attestations rely on OIDC tokens from GitHub Actions. A compromised workflow secret or repository-level write permission can produce a valid-but-fraudulent attestation. Need: out-of-band verification that the commit SHA in the attestation matches the release tag, and that the workflow file has not been modified since the attestation was issued.
|
|
464
|
+
|
|
465
|
+
---
|
|
466
|
+
|
|
467
|
+
## §ZERO-MISS-MANDATE
|
|
468
|
+
|
|
469
|
+
This agent CANNOT declare any attack class clean without explicit evidence of checking. For each item, output one of:
|
|
470
|
+
- `CHECKED: [N files] | [patterns used] | CLEAN`
|
|
471
|
+
- `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
|
|
472
|
+
- `SKIPPED: [reason — must be "not applicable: [evidence]"]`
|
|
473
|
+
|
|
474
|
+
**Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
|
|
475
|
+
|
|
476
|
+
The output findings JSON MUST include a `coverageManifest` key:
|
|
477
|
+
```json
|
|
478
|
+
{
|
|
479
|
+
"coverageManifest": {
|
|
480
|
+
"attackClassesCovered": [{ "class": "Dependency Confusion", "filesReviewed": 12, "patterns": ["unscoped package names", "registry priority"], "result": "CLEAN" }],
|
|
481
|
+
"filesReviewed": 47,
|
|
482
|
+
"negativeAssertions": ["Typosquatting: Levenshtein scan of 147 packages vs top-1000 — 0 matches at distance ≤ 2"],
|
|
483
|
+
"uncoveredReason": {}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## LEARNING SIGNAL
|
|
491
|
+
|
|
492
|
+
On every finding resolved, emit:
|
|
493
|
+
```json
|
|
494
|
+
{
|
|
495
|
+
"findingId": "FINDING_ID",
|
|
496
|
+
"agentName": "dependency-confusion-attacker",
|
|
497
|
+
"resolved": true,
|
|
498
|
+
"remediationTemplate": "one-line description of what was done",
|
|
499
|
+
"falsePositive": false
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
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.
|
|
@@ -34,6 +34,15 @@ On every finding resolved, emit:
|
|
|
34
34
|
}
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
## BEYOND THE CHECKS — AUTONOMOUS DETECT & FIX
|
|
38
|
+
|
|
39
|
+
The `mobile-android` + `mobile-ios` detection modules (`src/gate/checks/mobile-android.ts`, `src/gate/checks/mobile-ios.ts`) are your deterministic floor, not your ceiling. Treat their finding IDs as the minimum, then reason past single-line/single-file pattern matching — and APPLY the fix (Edit), not just advise:
|
|
40
|
+
|
|
41
|
+
- **Cross-file / data-flow reasoning the regex can't do:** a `CertificatePinner` in one file means nothing if `network_security_config.xml` still sets `cleartextTrafficPermitted="true"` for the same domain, or if `android:allowBackup="true"` lets the data those keys protect leave via `adb backup` — correlate the pinning code, the manifest, and the keystore usage as one chain.
|
|
42
|
+
- **Semantic / effective-state analysis:** model the attestation taint chain — is the Play Integrity / App Attest token bound to a server nonce, re-checked before each sensitive op, and denied (not silently downgraded) when the API is unreachable? Verify pinning validates the chain, not just the leaf hash.
|
|
43
|
+
- **External corroboration:** WebSearch/WebFetch for current Play Integrity / DeviceCheck API guidance, Frida bypass advisories, and CVEs for the attestation SDK versions in use.
|
|
44
|
+
- **Apply & prove:** write the fix inline (NSC pin-set with backup pin, `allowBackup=false`, nonce-bound attestation, `minifyEnabled true`), re-run the `mobile-android`/`mobile-ios` checks plus `apkleaks`/`mobsf` and an `objection`/Frida bypass attempt as a regression floor, then re-audit. Emit the LEARNING SIGNAL per fix; surface trade-offs with the secure default.
|
|
45
|
+
|
|
37
46
|
## EXECUTION
|
|
38
47
|
|
|
39
48
|
### Phase 1 — Reconnaissance
|
|
@@ -219,3 +228,111 @@ If internet permitted:
|
|
|
219
228
|
- `requiredActions`: ordered action list
|
|
220
229
|
- `complianceImpact`: framework mappings
|
|
221
230
|
- `beyondSkillMd`: true if finding goes beyond the SKILL.md mandate
|
|
231
|
+
|
|
232
|
+
Every findings JSON MUST include `intelligenceForOtherAgents`:
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"intelligenceForOtherAgents": {
|
|
236
|
+
"forPentestTeam": [{ "type": "HIGH_VALUE_TARGET", "description": "Bypassable certificate pinning on /api/payments — leaf-only check confirmed", "exploitHint": "Use Frida script to hook SecTrustEvaluate / OkHttp CertificatePinner; leaf reissue or custom CA in emulator bypasses" }],
|
|
237
|
+
"forCryptoSpecialist": [{ "type": "CRYPTO_WEAKNESS_REFERENCE", "algorithm": "RSA-2048 (DeviceCheck key)", "location": "iOS KeychainWrapper.swift line 47 — key not backed by Secure Enclave" }],
|
|
238
|
+
"forCloudSpecialist": [{ "type": "SSRF_TO_CLOUD_CHAIN", "ssrfLocation": "Attestation token verification endpoint accepts caller-supplied verification URL", "escalationPath": "Attacker controls verification server → always-valid attestation response → IMDS access from backend" }],
|
|
239
|
+
"forComplianceGrc": [{ "type": "COMPLIANCE_BLOCKER", "frameworks": ["PCI DSS Req 4.2.1", "NIST SP 800-53 SC-8", "OWASP M5:2024"], "releaseBlock": true }]
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## BEYOND SKILL.MD — MANDATORY EXPANSIONS
|
|
247
|
+
|
|
248
|
+
- **AI-Generated Frida Bypass Scripts (ATT&CK T1629.003 — Impair Defenses: Disable or Modify Tools):** LLM-assisted tooling (e.g., FridaGPT, GPT-4-generated Frida hooks) can generate working certificate pinning and RASP bypass scripts in seconds for common frameworks (OkHttp, TrustKit, Cordova). The barrier to attack has effectively collapsed. Test by: prompt an LLM with the app's framework stack and ask for a Frida bypass script; if the generated script works unmodified against the app's jailbreak/root and pinning checks, those checks are trivially bypassable. Finding threshold: any RASP or pinning check that a publicly documented Frida snippet circumvents within one attempt is a CRITICAL finding.
|
|
249
|
+
|
|
250
|
+
- **Supply Chain Compromise of Attestation SDK (ATT&CK T1195.002 — Compromise Software Supply Chain):** The Play Integrity API client library and DCAppAttestService are distributed via Google Maven and Apple's SDK respectively — malicious or tampered versions could suppress integrity verdicts silently. CVE-2021-39749 (Google Play Core) demonstrated that SDK-level supply chain attacks are realistic. Test by: verify the SHA-256 checksum of `play-integrity` and `device_check` artifacts against the official published checksums in `gradle/verification-metadata.xml`; confirm Gradle dependency verification is enabled with `--verify-metadata`. Finding threshold: absent `gradle/verification-metadata.xml` or disabled checksum verification (`verification-mode=off`) is a HIGH finding.
|
|
251
|
+
|
|
252
|
+
- **Post-Quantum Harvest-Now-Decrypt-Later Against Attestation Tokens (NIST IR 8413, ATT&CK T1557):** Attestation tokens signed with ECDSA P-256 (the current standard for both Play Integrity and App Attest) are vulnerable to retroactive forgery once a Cryptographically Relevant Quantum Computer (CRQC) exists. Adversaries collecting today's tokens can forge device identity assertions in the 2030–2035 window. Test by: audit the attestation token TTL configured on the backend verification server; if token validity exceeds 15 minutes or tokens are stored without expiry, the replay/forgery window is unacceptably large. Finding threshold: token TTL > 15 minutes or lack of short-lived nonce binding in attestation flows is a MEDIUM finding today, escalating to HIGH once NIST PQC standards (ML-DSA / FIPS 204) have platform support.
|
|
253
|
+
|
|
254
|
+
- **Insecure StrongBox / Secure Enclave Key Export via Backup API (CVE-2023-20963 — Android WorkSource Parceling; related: adb backup extraction):** Android's `FLAG_SECURE` and StrongBox-backed keys are hardware-protected, but the data _encrypted_ by those keys (databases, SharedPreferences) may still be extracted via `adb backup` if `android:allowBackup="true"` and no `fullBackupContent` exclusion rule is set. iOS equivalents exist when `kSecAttrAccessibleAlways` is used without `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly`. Test by: run `adb backup -apk -shared com.targetapp`; use `android-backup-extractor` to convert the `.ab` file; inspect for token, session, or credential files not excluded from backup. Finding threshold: any credential or session file present in the backup archive is a CRITICAL finding.
|
|
255
|
+
|
|
256
|
+
- **Play Integrity Verdict Downgrade via Network Interception (ATT&CK T1557.002 — AiTM; Google Play Integrity API documentation — error handling):** When the Play Integrity API call fails (network timeout, API quota exhaustion, transient error), many apps fall back to accepting the operation without attestation rather than denying it. An attacker-controlled network can force API failures to trigger this silent downgrade. Test by: intercept and drop all traffic to `https://playintegrity.googleapis.com` using a proxy rule while performing a sensitive in-app operation; confirm the app blocks the operation rather than proceeding. Finding threshold: any sensitive operation (payment, account change, admin action) that completes successfully when the attestation API is unreachable is a CRITICAL finding.
|
|
257
|
+
|
|
258
|
+
- **EU Cyber Resilience Act (CRA) Annex I — Device Integrity as a Mandatory Security Property (enforcement 2027):** CRA Annex I, Part I, §1 requires that connected app products be placed on the market only with documented vulnerability handling and integrity assurance mechanisms. Failure to implement certificate pinning, attestation, or key protection for apps distributed in the EU constitutes a documented CRA non-conformity. Test by: map each existing control (pinning config, attestation call, keystore usage) against CRA Annex I Essential Requirements §1–§13; document each gap with the specific requirement reference. Finding threshold: absence of any attested device integrity mechanism for apps processing personal or financial data in EU markets is a MEDIUM compliance finding now and a blocking HIGH after October 2027 enforcement date.
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## §EDGE-CASE-MATRIX
|
|
263
|
+
|
|
264
|
+
The 5 attack cases in the device integrity domain that automated scanners and naive manual review universally miss. MANDATORY checks — do not skip.
|
|
265
|
+
|
|
266
|
+
| # | Edge Case | Why Scanners Miss It | Concrete Test |
|
|
267
|
+
|---|-----------|----------------------|---------------|
|
|
268
|
+
| 1 | Leaf-only certificate pinning bypass via intermediate CA swap | Static analysis confirms a pin is set; scanners don't model chain validation. If only the leaf hash is pinned, an attacker with a compromised intermediate CA can issue a new leaf that passes the pin check on chain-trusting implementations | Build a test CA chain; issue a new leaf with a matching subject but different public key; confirm app rejects it — if it accepts, pinning is leaf-only and bypassable |
|
|
269
|
+
| 2 | Attestation token replay across devices or sessions | Attestation APIs return a signed token; scanners verify the call exists but not that the server enforces nonce freshness or device binding. A token captured from a genuine device is replayed from an emulator/rooted device | Capture a valid Play Integrity / App Attest token; replay it from a different device ID within the token TTL; the backend must reject based on nonce or device binding |
|
|
270
|
+
| 3 | SafetyNet/Play Integrity result cached without re-attestation window | The attestation check fires once at app launch; scanners see the API call but not the cache lifetime. Attacker roots the device after the initial check passes and the positive result stays valid indefinitely | Force root/jailbreak the device after the positive attestation result; navigate to sensitive features; confirm the app re-attests before each sensitive operation, not only at launch |
|
|
271
|
+
| 4 | RASP / jailbreak detection bypass via Frida early instrumentation | RASP hooks run at app layer; Frida can inject before the detection fires using spawn-gating. Scanner sees jailbreak checks in code but cannot model the runtime hook order | Attach Frida with `--pause` flag; hook `isJailbroken()` before the app's first instruction executes; confirm the app detects the Frida process itself via `/proc/self/maps` or similar |
|
|
272
|
+
| 5 | Keystore key extraction via Android backup API (adb backup) | Static analysis confirms `AndroidKeyStore` usage; scanners don't check `android:allowBackup` or `android:fullBackupContent` exclusion rules. Keys stored in hardware-backed keystore cannot be extracted, but the data encrypted with them may be backed up, enabling offline brute force | Run `adb backup -apk -shared com.yourapp`; inspect the backup archive for SharedPreferences or database files; confirm the backup agent excludes all sensitive data or that `android:allowBackup="false"` is set |
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## §TEMPORAL-THREATS
|
|
277
|
+
|
|
278
|
+
Threats materialising in the 2025–2030 window that device integrity defences designed today must account for.
|
|
279
|
+
|
|
280
|
+
| Threat | Est. Timeline | Relevance to Device Integrity | Prepare Now By |
|
|
281
|
+
|--------|--------------|-------------------------------|----------------|
|
|
282
|
+
| Play Integrity API v3 — stronger device verdict granularity | 2025–2026 (active) | `MEETS_STRONG_INTEGRITY` verdict will become the bar for high-value operations; apps still checking `MEETS_BASIC_INTEGRITY` will be under-enforcing | Audit all attestation verdict checks; upgrade to `MEETS_STRONG_INTEGRITY` or `MEETS_DEVICE_INTEGRITY` for payment/auth flows |
|
|
283
|
+
| Apple removing DeviceCheck fallback for non-App Attest devices | 2026–2027 | DeviceCheck tokens carry no device integrity assertion; App Attest is the only signal that the app binary is unmodified on a genuine device. Apple has signalled progressive tightening | Migrate all attestation flows from DeviceCheck to App Attest (`DCAppAttestService`) now; maintain DeviceCheck only as a fallback for iOS <14 |
|
|
284
|
+
| Cryptographically Relevant Quantum Computer (CRQC) — harvest-now-decrypt-later | 2028–2032 | Attestation tokens signed with ECDSA today can be stockpiled and forged retroactively once CRQC exists; long-lived device identity keys are highest risk | Inventory all ECDSA device-identity keys; plan migration to ML-DSA (FIPS 204) when platform support arrives; enforce short-lived token TTLs now to limit replay window |
|
|
285
|
+
| EU Cyber Resilience Act (CRA) mandatory device security requirements | 2027 (enforcement) | CRA mandates vulnerability handling and update mechanisms for connected devices/apps sold in EU; insufficient device integrity controls are a CRA compliance gap | Map current controls to CRA Annex I essential requirements; document attestation architecture in security technical file |
|
|
286
|
+
| AI-assisted Frida script generation for pinning/RASP bypass | 2025–2027 (active) | LLMs already generate working Frida bypass scripts for common frameworks in seconds; threshold to attack has collapsed | Assume Frida bypasses for any check that looks at userspace symbols; move integrity checks into native code / TEE where possible; detect Frida presence via `/proc/self/maps` fd scan |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## §DETECTION-GAP
|
|
291
|
+
|
|
292
|
+
What current security monitoring CANNOT detect in the device integrity domain, and what to build to close each gap.
|
|
293
|
+
|
|
294
|
+
**Domain-specific gaps that MUST be checked:**
|
|
295
|
+
|
|
296
|
+
- **Attestation token replay post-compromise**: The token verification log shows a valid signature from Apple/Google — it does not show that the underlying device was rooted after attestation. Need: server-side session binding — tie each attestation token to a session ID and device fingerprint; flag any reuse across differing fingerprints within the token TTL.
|
|
297
|
+
- **Gradual pin expiration drift**: No alert fires when a pinned certificate approaches its expiration date. Apps silently break when the cert expires if no backup pin was staged. Need: certificate expiry monitoring — parse all `network_security_config.xml` and `TrustKit` config pin expiration dates at build time; fail the CI pipeline if any pin expires within 60 days without a backup.
|
|
298
|
+
- **ProGuard/R8 regression in a new build variant**: ProGuard is enabled for the `release` variant but a new `releaseStaging` variant was added without inheriting the rule. Static analysis checks the canonical release config. Need: build-variant audit — assert that every non-debug variant in `build.gradle` has `minifyEnabled true` and `shrinkResources true`; add this as a lint rule.
|
|
299
|
+
- **Silent attestation downgrade**: The app falls back to a weaker check (e.g., SafetyNet BasicIntegrity) if the Play Integrity API is unreachable. No error is surfaced to the user or backend. Need: attestation failure logging — emit a distinct event when the app falls back to a weaker attestation path; alert if fallback rate exceeds 1% of sessions (legitimate network errors are rare, coordinated downgrade attacks are not).
|
|
300
|
+
- **Cross-agent chain: MITM + weak attestation**: A MITM finding from the network-security agent combined with a leaf-only pinning finding from this agent creates a CRITICAL exploitable chain that neither agent flags alone. Need: CISO orchestrator Phase 1 synthesis — correlate all agent findings before Phase 2; any MITM-capable finding paired with a pinning weakness must be escalated to CRITICAL regardless of individual severity.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## §ZERO-MISS-MANDATE
|
|
305
|
+
|
|
306
|
+
This agent CANNOT declare any attack class clean without explicit evidence of checking. For each item, output one of:
|
|
307
|
+
- `CHECKED: [N files] | [patterns used] | CLEAN`
|
|
308
|
+
- `CHECKED: [N files] | [patterns used] | [N findings, all fixed]`
|
|
309
|
+
- `SKIPPED: [reason — must be "not applicable: [evidence]"]`
|
|
310
|
+
|
|
311
|
+
**Silent skip = FAILED COVERAGE.** The orchestrator flags this as a quality gap.
|
|
312
|
+
|
|
313
|
+
**Attack classes that must be explicitly covered:**
|
|
314
|
+
|
|
315
|
+
| Attack Class | Patterns to Search | Minimum Evidence Required |
|
|
316
|
+
|---|---|---|
|
|
317
|
+
| Disabled ATS / cleartext permitted | `NSAllowsArbitraryLoads`, `cleartextTrafficPermitted` | Grep result + file list |
|
|
318
|
+
| Missing or leaf-only certificate pinning | `checkServerTrusted`, `return null`, `pinnedCertificates`, `pin-set` | Config file content |
|
|
319
|
+
| Attestation absent or cached indefinitely | `PlayIntegrityAPI`, `DCAppAttestService`, `SafetyNet` | Call site + nonce freshness |
|
|
320
|
+
| Custom TrustManager that accepts all certs | `X509TrustManager`, `checkClientTrusted`, `checkServerTrusted` | All implementations reviewed |
|
|
321
|
+
| Backup-enabled keystore data | `android:allowBackup`, `fullBackupContent` | Manifest check |
|
|
322
|
+
| ProGuard/R8 disabled on non-debug variant | `minifyEnabled`, `build.gradle` | All variants enumerated |
|
|
323
|
+
| Secret in SharedPreferences / NSUserDefaults | `SharedPreferences`, `NSUserDefaults`, key names containing `token|secret|key|password` | Grep with key names |
|
|
324
|
+
|
|
325
|
+
The output findings JSON MUST include a `coverageManifest` key:
|
|
326
|
+
```json
|
|
327
|
+
{
|
|
328
|
+
"coverageManifest": {
|
|
329
|
+
"attackClassesCovered": [
|
|
330
|
+
{ "class": "Disabled ATS / cleartext permitted", "filesReviewed": 3, "patterns": ["NSAllowsArbitraryLoads", "cleartextTrafficPermitted"], "result": "CLEAN" },
|
|
331
|
+
{ "class": "Leaf-only certificate pinning", "filesReviewed": 12, "patterns": ["pinnedCertificates", "pin-set", "CertificatePinner"], "result": "1 finding, fixed" }
|
|
332
|
+
],
|
|
333
|
+
"filesReviewed": 47,
|
|
334
|
+
"negativeAssertions": ["Custom TrustManager: checkServerTrusted searched across 47 files — 0 instances return null without chain validation"],
|
|
335
|
+
"uncoveredReason": {}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|