blitzstrike 2.4.68 → 2.4.69
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/CHANGELOG.md +21 -0
- package/dist/index.js +109 -6
- package/intelligence/cwe_map.json +321 -63
- package/intelligence/patterns.json +511 -100
- package/intelligence/variants.json +28 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,27 @@ All notable changes to Blitz Strike are documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [2.4.69] — 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Added — Supply-chain detectors (dependency confusion + ML model loading)
|
|
11
|
+
|
|
12
|
+
- New `dependency_confusion` detector (CWE-427): flags a manifest/build file that
|
|
13
|
+
resolves a package from a PUBLIC registry (--index-url/--extra-index-url to
|
|
14
|
+
pypi.org/npmjs.org/rubygems.org), or references a scoped internal package
|
|
15
|
+
(@company/pkg) with no private registry pinned — the squattable-name confusion
|
|
16
|
+
vector. Manifest-gated by file name.
|
|
17
|
+
- New `ml_supply_chain` detector (CWE-502): flags untrusted AI/ML model loading —
|
|
18
|
+
`torch.load` without `weights_only=True`, `joblib.load`, `keras.models.load_model`,
|
|
19
|
+
and `np.load(allow_pickle=True)` (source-agnostic, the flag IS the signal) —
|
|
20
|
+
pickle RCE on load. Complementary to the deserialization detector.
|
|
21
|
+
- Wired into the full pipeline: CWE map (now 64), patterns (22), variants (74, all
|
|
22
|
+
fired), synonyms (69 aliases), severity VRT map, verification harness (now 21/21
|
|
23
|
+
detectors TP+TN).
|
|
24
|
+
- FIXED a severity gap the interconnection audit exposed: the VRT map was missing
|
|
25
|
+
the 4 modern detectors added earlier (llm_injection, graphql_exposure,
|
|
26
|
+
oauth_misconfig, grpc_reflection) — they now carry proper VRT tiers, and a new
|
|
27
|
+
regression test asserts every detector type has a non-"unclassified" severity.
|
|
28
|
+
|
|
8
29
|
## [2.4.68] — 2026-09-14
|
|
9
30
|
|
|
10
31
|
### Added — Git-history secret mining + leaked-key validation
|
package/dist/index.js
CHANGED
|
@@ -16263,6 +16263,8 @@ function detectComplexBugs(code, file) {
|
|
|
16263
16263
|
detectGraphqlExposure(code, file, out);
|
|
16264
16264
|
detectOauthMisconfig(code, file, out);
|
|
16265
16265
|
detectGrpcReflection(code, file, out);
|
|
16266
|
+
detectDependencyConfusion(code, file, out);
|
|
16267
|
+
detectMlSupplyChain(code, file, out);
|
|
16266
16268
|
out.push(...detectWrongSanitizer(code, file));
|
|
16267
16269
|
out.push(...detectMissingAuthz(code, file));
|
|
16268
16270
|
const seen = new Set;
|
|
@@ -16679,6 +16681,78 @@ function detectGrpcReflection(code, file, out) {
|
|
|
16679
16681
|
});
|
|
16680
16682
|
}
|
|
16681
16683
|
}
|
|
16684
|
+
function detectDependencyConfusion(code, file, out) {
|
|
16685
|
+
const isManifest = /package\.json|requirements|pipfile|gemfile|go\.mod|pom\.xml|setup\.py|pyproject|\.npmrc|pip\.conf|dockerfile|\.ya?ml$/i.test(file);
|
|
16686
|
+
if (!isManifest)
|
|
16687
|
+
return;
|
|
16688
|
+
const ls = lines2(code);
|
|
16689
|
+
const idxRe = /--(?:extra-)?index-url\s+["']?(https?:\/\/[^"'<\s]+)["']?/gi;
|
|
16690
|
+
let m;
|
|
16691
|
+
while ((m = idxRe.exec(code)) !== null) {
|
|
16692
|
+
if (/pypi\.org|pythonhosted|npmjs\.org|rubygems\.org|golang\.org|crates\.io|maven\.apache\.org/i.test(m[1])) {
|
|
16693
|
+
const ln = lineNo2(code, m.index);
|
|
16694
|
+
out.push({
|
|
16695
|
+
file,
|
|
16696
|
+
line: ln,
|
|
16697
|
+
type: "dependency_confusion",
|
|
16698
|
+
category: "Dependency confusion — public registry in resolution path",
|
|
16699
|
+
severity: "high",
|
|
16700
|
+
evidence: (ls[ln - 1] ?? "").trim(),
|
|
16701
|
+
detail: `A public registry (${m[1]}) is the resolution source — an internal package name that exists or can be squatted on the public registry resolves there instead of the private one, pulling attacker-controlled code (CWE-427). Pin a private registry and namespace internal packages uniquely.`
|
|
16702
|
+
});
|
|
16703
|
+
}
|
|
16704
|
+
}
|
|
16705
|
+
const hasPrivateRegistry = /--(?:index-url|registry)\s+["']?(?!https?:\/\/pypi\.org|https?:\/\/registry\.npmjs\.org)/i.test(code) || /(?:registry|index[-_]url)\s*[:=]\s*["']https?:\/\/(?!.*(?:pypi\.org|registry\.npmjs\.org))/i.test(code);
|
|
16706
|
+
if (!hasPrivateRegistry) {
|
|
16707
|
+
const scopedRe = /["'](@[a-z0-9][a-z0-9-]*\/[a-z0-9_.-]+)["']/g;
|
|
16708
|
+
while ((m = scopedRe.exec(code)) !== null) {
|
|
16709
|
+
const ln = lineNo2(code, m.index);
|
|
16710
|
+
out.push({
|
|
16711
|
+
file,
|
|
16712
|
+
line: ln,
|
|
16713
|
+
type: "dependency_confusion",
|
|
16714
|
+
category: "Dependency confusion — scoped package, no private registry",
|
|
16715
|
+
severity: "medium",
|
|
16716
|
+
evidence: (ls[ln - 1] ?? "").trim(),
|
|
16717
|
+
detail: `The scoped package ${m[1]} is referenced but no private registry is pinned — if the @scope is not registered/reserved on the public registry, an attacker can publish ${m[1]} there and the build will pull malicious code (CWE-427). Verify the registry resolution and pin it.`
|
|
16718
|
+
});
|
|
16719
|
+
}
|
|
16720
|
+
}
|
|
16721
|
+
}
|
|
16722
|
+
function detectMlSupplyChain(code, file, out) {
|
|
16723
|
+
const ls = lines2(code);
|
|
16724
|
+
const clean = stripCommentsOnly(code);
|
|
16725
|
+
const sinks = [
|
|
16726
|
+
{ re: /torch\.load\s*\(/g, name: "torch.load", note: "uses pickle; pass weights_only=True", skipIfSafe: /weights_only\s*=\s*True/ },
|
|
16727
|
+
{ re: /\bjoblib\.load\s*\(/g, name: "joblib.load", note: "uses pickle (no safe flag)" },
|
|
16728
|
+
{ re: /(?:tf\.)?keras\.models\.load_model\s*\(/g, name: "keras load_model", note: "deserializes the model graph (pickle/h5)" },
|
|
16729
|
+
{ re: /\bnp\.load\s*\(/g, name: "np.load", note: "allow_pickle=True is RCE", requireFlag: /allow_pickle\s*=\s*True/i }
|
|
16730
|
+
];
|
|
16731
|
+
for (const s of sinks) {
|
|
16732
|
+
s.re.lastIndex = 0;
|
|
16733
|
+
let m;
|
|
16734
|
+
while ((m = s.re.exec(clean)) !== null) {
|
|
16735
|
+
const ln = lineNo2(code, m.index);
|
|
16736
|
+
const l = ls[ln - 1] ?? "";
|
|
16737
|
+
if (s.skipIfSafe && s.skipIfSafe.test(l))
|
|
16738
|
+
continue;
|
|
16739
|
+
if (s.requireFlag && !s.requireFlag.test(l))
|
|
16740
|
+
continue;
|
|
16741
|
+
const flagIsSignal = s.requireFlag != null;
|
|
16742
|
+
if (!flagIsSignal && !SOURCE_TOKENS3.test(l) && !/https?:\/\//.test(l) && !/download|request|upload|user|input|temp|tmp/i.test(l))
|
|
16743
|
+
continue;
|
|
16744
|
+
out.push({
|
|
16745
|
+
file,
|
|
16746
|
+
line: ln,
|
|
16747
|
+
type: "ml_supply_chain",
|
|
16748
|
+
category: "ML supply chain — untrusted model load",
|
|
16749
|
+
severity: "high",
|
|
16750
|
+
evidence: l.trim(),
|
|
16751
|
+
detail: `\`${s.name}\` loads a model from an untrusted source — ${s.note}. A poisoned model file executes arbitrary code on load (CWE-502). Pin hashes, load from a trusted artifact store, and use the safe flag where available.`
|
|
16752
|
+
});
|
|
16753
|
+
}
|
|
16754
|
+
}
|
|
16755
|
+
}
|
|
16682
16756
|
var SOURCE_TOKENS3, MAGIC_METHODS, SECRET_FIELD_RE, SECRET_PLACEHOLDER_RE, ENTROPY_EXCLUDE_VAR;
|
|
16683
16757
|
var init_complex_bugs = __esm(() => {
|
|
16684
16758
|
init_security_state();
|
|
@@ -16694,8 +16768,8 @@ var init_complex_bugs = __esm(() => {
|
|
|
16694
16768
|
// src/verify-harness.ts
|
|
16695
16769
|
function runVerificationHarness() {
|
|
16696
16770
|
const cases = CASES.map((c) => {
|
|
16697
|
-
const pos = detectComplexBugs(c.positive, "positive.php").filter((f) => f.type === c.detector);
|
|
16698
|
-
const neg = detectComplexBugs(c.negative, "negative.php").filter((f) => f.type === c.detector);
|
|
16771
|
+
const pos = detectComplexBugs(c.positive, c.file ?? "positive.php").filter((f) => f.type === c.detector);
|
|
16772
|
+
const neg = detectComplexBugs(c.negative, c.file ?? "negative.php").filter((f) => f.type === c.detector);
|
|
16699
16773
|
const positive_fired = pos.length > 0;
|
|
16700
16774
|
const negative_fired = neg.length > 0;
|
|
16701
16775
|
const tp = positive_fired;
|
|
@@ -16860,6 +16934,20 @@ $r = openai.chat.completions.create(['messages' => [['role' => 'user', 'content'
|
|
|
16860
16934
|
detector: "grpc_reflection",
|
|
16861
16935
|
positive: PHP(`$server->addService(enable_server_reflection());`),
|
|
16862
16936
|
negative: PHP(`$server->addService($my_service);`)
|
|
16937
|
+
},
|
|
16938
|
+
{
|
|
16939
|
+
id: "dependency-confusion",
|
|
16940
|
+
detector: "dependency_confusion",
|
|
16941
|
+
file: "requirements.txt",
|
|
16942
|
+
positive: `--extra-index-url https://pypi.org/simple\\nnumpy==1.24.0\\n`,
|
|
16943
|
+
negative: `--index-url https://pypi.internal.company.com/simple\\nnumpy==1.24.0\\n`
|
|
16944
|
+
},
|
|
16945
|
+
{
|
|
16946
|
+
id: "ml-supply-chain",
|
|
16947
|
+
detector: "ml_supply_chain",
|
|
16948
|
+
file: "train.py",
|
|
16949
|
+
positive: `import torch\\nmodel = torch.load(downloaded_model)\\n`,
|
|
16950
|
+
negative: `import torch\\nmodel = torch.load("model.pt", weights_only=True)\\n`
|
|
16863
16951
|
}
|
|
16864
16952
|
];
|
|
16865
16953
|
});
|
|
@@ -16879,7 +16967,7 @@ function loadVariants() {
|
|
|
16879
16967
|
function scanVariants() {
|
|
16880
16968
|
const variants = loadVariants().filter((v) => !CROSS_FILE_ONLY.has(v.class));
|
|
16881
16969
|
const results = variants.map((v, i) => {
|
|
16882
|
-
const findings = detectComplexBugs(v.code, `variant-${i}.php`).filter((f) => f.type === v.class);
|
|
16970
|
+
const findings = detectComplexBugs(v.code, v.file ?? `variant-${i}.php`).filter((f) => f.type === v.class);
|
|
16883
16971
|
return { id: `variant-${i}`, class: v.class, fired: findings.length > 0, note: v.note };
|
|
16884
16972
|
});
|
|
16885
16973
|
const per_class = {};
|
|
@@ -57791,7 +57879,16 @@ var ALIASES = {
|
|
|
57791
57879
|
"header injection": "crlf_injection",
|
|
57792
57880
|
"http response splitting": "crlf_injection",
|
|
57793
57881
|
"wrong sanitizer": "wrong_sanitizer",
|
|
57794
|
-
"wrong context sanitization": "wrong_sanitizer"
|
|
57882
|
+
"wrong context sanitization": "wrong_sanitizer",
|
|
57883
|
+
"dependency confusion": "dependency_confusion",
|
|
57884
|
+
"dep confusion": "dependency_confusion",
|
|
57885
|
+
"supply chain": "dependency_confusion",
|
|
57886
|
+
"supply chain attack": "dependency_confusion",
|
|
57887
|
+
"ml supply chain": "ml_supply_chain",
|
|
57888
|
+
"ai supply chain": "ml_supply_chain",
|
|
57889
|
+
"model poisoning": "ml_supply_chain",
|
|
57890
|
+
"ml security": "ml_supply_chain",
|
|
57891
|
+
"ai ml security": "ml_supply_chain"
|
|
57795
57892
|
};
|
|
57796
57893
|
function normalize(term) {
|
|
57797
57894
|
return term.trim().toLowerCase().replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -58076,7 +58173,13 @@ var VRT_MAP = {
|
|
|
58076
58173
|
prototype_pollution: { vrt: "injection > prototype_pollution", priority: "P2", severity: "high", rationale: "Object prototype corruption can escalate to code execution in gadget-heavy runtimes." },
|
|
58077
58174
|
crlf_injection: { vrt: "injection > crlf_injection", priority: "P3", severity: "medium", rationale: "Header injection enables cookie poisoning or cache poisoning." },
|
|
58078
58175
|
missing_nonce: { vrt: "broken_access_control > cross_site_request_forgery", priority: "P3", severity: "medium", rationale: "A state-changing action lacks an anti-CSRF token." },
|
|
58079
|
-
wrong_sanitizer: { vrt: "injection > improper_input_validation", priority: "P3", severity: "medium", rationale: "A value sanitized for the wrong context still reaches the sink; severity follows the sink." }
|
|
58176
|
+
wrong_sanitizer: { vrt: "injection > improper_input_validation", priority: "P3", severity: "medium", rationale: "A value sanitized for the wrong context still reaches the sink; severity follows the sink." },
|
|
58177
|
+
llm_injection: { vrt: "injection > prompt_injection", priority: "P2", severity: "high", rationale: "Prompt injection can exfiltrate the system prompt, RAG data, or trigger privileged tool use." },
|
|
58178
|
+
graphql_exposure: { vrt: "misconfiguration > graphql_introspection", priority: "P4", severity: "low", rationale: "GraphQL introspection exposes the schema but is not directly exploitable." },
|
|
58179
|
+
oauth_misconfig: { vrt: "authentication > oauth_misconfiguration", priority: "P2", severity: "high", rationale: "An OAuth/open-redirect misconfiguration can leak authorization codes → account takeover." },
|
|
58180
|
+
grpc_reflection: { vrt: "misconfiguration > debug_information_exposure", priority: "P5", severity: "low", rationale: "gRPC reflection exposes the API contract but is not directly exploitable." },
|
|
58181
|
+
dependency_confusion: { vrt: "insecure_design > dependency_confusion", priority: "P2", severity: "high", rationale: "An internal package resolves from a squattable public registry → attacker-controlled code in the build." },
|
|
58182
|
+
ml_supply_chain: { vrt: "injection > insecure_deserialization", priority: "P1", severity: "critical", rationale: "Untrusted model loading via pickle (torch/joblib/numpy) → arbitrary code execution on load." }
|
|
58080
58183
|
};
|
|
58081
58184
|
function severityCalibrate(input) {
|
|
58082
58185
|
const type = input.type?.toLowerCase() ?? "";
|
|
@@ -59596,7 +59699,7 @@ function createServer() {
|
|
|
59596
59699
|
` + `- A hard block (Cloudflare/WAF/IP-block/captcha) is NOT the end: mark the finding blocked + note the required vantage (residential / authorized / correct-SNI / --resolve direct-to-origin), then CONTINUE to the next lead (origin bypass, non-prod cluster, mobile APK, subdomain).
|
|
59597
59700
|
` + `- Keep trying every lead AND every chain step until each is verified/executed or blocked, THEN generate_report. Never deliver a bare surface map, and never stop at 'found X' when X enables more.
|
|
59598
59701
|
|
|
59599
|
-
` + "TWO PATHS:\\n" + "- Source path on disk -> blitz_scan / taint_file / eagle_eye2 (static).\\n" + "- Live URL -> live_recon / active_scan / strike_verify (web-hunting).\\n\\n" + "DEEPEN A FINDING: attack_plan(target, tech, params) to get the prioritized vector plan (decide what to test next with data); list_chains (escalation), chain_links (compose), technique_lookup(cls), payload_lookup, bypass_lookup (blocked). Ground any detector hit empirically with pattern_lookup(id) — it returns the class's CWE, real-world signature, escalation chains, citable references, per-class bypass techniques, and the high-value assets (crown jewels) that class hits, so a raw hit becomes a class-aware finding. Resolve free-form terminology first with synonym_lookup(term) (IDOR/BOLA/SQLi/prompt-injection → canonical id). For an llm_injection hit, its pattern carries a validation discipline — the RUN-TWICE RULE (reproduce token-for-token across two fresh sessions), NON-GUESSABLE ANCHOR (must leak a real key/URL, not a plausible guess), and OOB PROOF (a verifiable callback log) — apply all three before reporting. BEFORE generating a report, run submission_gate(...) and only ship a finding that passes all 7 questions (reproducible, in-scope, real-impact, no-privileged-assumption, verified-live, evidence-redacted, severity-derived); one false = kill it. Calibrate severity with severity_calibrate(type, cvss) to get a P1–P5 tier + VRT-style category. Start each engagement with engagement_scaffold(target, scope) for the folder + scope.md structure, and check data_refresh() to confirm the data layers are consistent. Phase doctrine: read_skill(bs-orchestrate-engagement | bs-web-hunting | bs-source-audit | bs-verify-finding). Campaign plan: read_playbook(target-type). On any failure call retry_guidance(signal) / model_fallback(signal) before giving up.\n" + "KNOWLEDGE BASE (discover, don't guess): skillLookup(topic) / listSkills for the 40 attack-path + hunting skills (ap-*, hp-*, bs-*); list_attack_vectors / attack_vectors(cat) for the 34-category vector taxonomy; taxonomy(kind) for OWASP/CWE/ASVS/API-top-10; read_playbook(type) for the 17 campaign playbooks; list_manuals / read_tool_manual for 317 tool references; list_tools / run_catalog_tool for the 141-tool catalog. Every tool, skill, and data layer is reachable from these. CROSS-TARGET INTELLIGENCE: strike_resolve auto-records confirmed/false_positive verdicts into the empirical ledger; query it with intelligence(action=hit_rates/top_vectors/recall) so a new target on a known tech inherits historical hit-rates (attack_plan already blends them into success_probability). intelligence(action=recall, tech, target) is the per-engagement pattern recall — it returns which patterns historically CONFIRMED on that tech (prioritize them) versus which only ever produced false positives (avoid them), so a new engagement starts from the empirical playbook of past ones. LIVE PENTEST + TARGETING (black-box, WAF-safe): cache_gap(base_url, endpoint) fuzzes path-normalization + static-extension variants for cache deception/poisoning; blind_oracle(base_url, param, value) detects which SINK a param reaches (sql/ssti/xss) via benign arithmetic (id=1+0, test${7*7}) WITHOUT a malicious payload; param_precedence(base_url, param, A, B) maps duplicate-parameter precedence (first/last-wins) for WAF-bypass. SOURCE TARGETING: action_surface(code) maps every wp_ajax_* action to its vuln class + DERIVED priority (what to look for WHERE); security_state(sanitizers, sink) gives a wrong-context sanitization verdict; framework_knowledge(framework) returns auth/nonce primitives for 9 frameworks; variant_scan(root, signature) mass-sweeps an install base for ONE bug family; patch_analyze(old, new) REVERSES a security patch into the 0-day, and its mine_signature feeds variant_scan to sweep unpatched copies. All of these are DETECTION HINTS — verify each live (strike_verify / browser_validate) before it enters the report. NEWEST DETECTORS — understand AND try them: variant_scan also emits priv_esc (privilege escalation — a role/capability/user change fed by request input, traced cross-file via reverse call-graph, e.g. set_role($id, sanitize_key($_POST['um-role'])) or update_user_meta(...,'wp_capabilities', $_POST[...])) and flags uploadAllow=>array('all') unrestricted-upload configs as file_upload (the file-manager/connector shape). TO TRY a priv_esc hit: submit the role field with 'administrator' (or send wp_capabilities meta) and confirm the account actually gains admin. TO TRY an unrestricted-upload hit: POST a .php/.phtml and confirm it lands web-reachable + executes. variant_scan also emits hardcoded_secret (CWE-798) in three tiers: a secret field (api_key/db_password/access_token/aws_*) assigned a literal (HIGH), a known secret FORMAT (JWT eyJ…/AWS AKIA…/GitHub ghp_…/Slack xoxb-…/…) regardless of name (HIGH), or a high-entropy suspect token (MEDIUM — verify before reporting). Verify a frontend/JS secret live via drive_devtools (inspect the JS bundle / network response and confirm the key is actually exposed), and for a backend secret confirm it is reachable/valid. A static hit is a HYPOTHESIS until verified live — never report unverified. For a repo, also scan_git_history(root) — secrets DELETED from HEAD still live in .git history (the removed-later-is-not-fixed trap), and it feeds every recovered pre-deletion blob through the same secret detector. Once you recover a credential, prove it is still ACTIVE with validate_leaked_key(apiBase, endpoints, key|blobUrl) — a READ-ONLY differential test (401-without-key vs 200-with-key = auth bypass PROVEN).\n" + `PRECISION ANALYSIS — chrome-devtools MCP is MANDATORY, not optional:
|
|
59702
|
+
` + "TWO PATHS:\\n" + "- Source path on disk -> blitz_scan / taint_file / eagle_eye2 (static).\\n" + "- Live URL -> live_recon / active_scan / strike_verify (web-hunting).\\n\\n" + "DEEPEN A FINDING: attack_plan(target, tech, params) to get the prioritized vector plan (decide what to test next with data); list_chains (escalation), chain_links (compose), technique_lookup(cls), payload_lookup, bypass_lookup (blocked). Ground any detector hit empirically with pattern_lookup(id) — it returns the class's CWE, real-world signature, escalation chains, citable references, per-class bypass techniques, and the high-value assets (crown jewels) that class hits, so a raw hit becomes a class-aware finding. Resolve free-form terminology first with synonym_lookup(term) (IDOR/BOLA/SQLi/prompt-injection → canonical id). For an llm_injection hit, its pattern carries a validation discipline — the RUN-TWICE RULE (reproduce token-for-token across two fresh sessions), NON-GUESSABLE ANCHOR (must leak a real key/URL, not a plausible guess), and OOB PROOF (a verifiable callback log) — apply all three before reporting. BEFORE generating a report, run submission_gate(...) and only ship a finding that passes all 7 questions (reproducible, in-scope, real-impact, no-privileged-assumption, verified-live, evidence-redacted, severity-derived); one false = kill it. Calibrate severity with severity_calibrate(type, cvss) to get a P1–P5 tier + VRT-style category. Start each engagement with engagement_scaffold(target, scope) for the folder + scope.md structure, and check data_refresh() to confirm the data layers are consistent. Phase doctrine: read_skill(bs-orchestrate-engagement | bs-web-hunting | bs-source-audit | bs-verify-finding). Campaign plan: read_playbook(target-type). On any failure call retry_guidance(signal) / model_fallback(signal) before giving up.\n" + "KNOWLEDGE BASE (discover, don't guess): skillLookup(topic) / listSkills for the 40 attack-path + hunting skills (ap-*, hp-*, bs-*); list_attack_vectors / attack_vectors(cat) for the 34-category vector taxonomy; taxonomy(kind) for OWASP/CWE/ASVS/API-top-10; read_playbook(type) for the 17 campaign playbooks; list_manuals / read_tool_manual for 317 tool references; list_tools / run_catalog_tool for the 141-tool catalog. Every tool, skill, and data layer is reachable from these. CROSS-TARGET INTELLIGENCE: strike_resolve auto-records confirmed/false_positive verdicts into the empirical ledger; query it with intelligence(action=hit_rates/top_vectors/recall) so a new target on a known tech inherits historical hit-rates (attack_plan already blends them into success_probability). intelligence(action=recall, tech, target) is the per-engagement pattern recall — it returns which patterns historically CONFIRMED on that tech (prioritize them) versus which only ever produced false positives (avoid them), so a new engagement starts from the empirical playbook of past ones. LIVE PENTEST + TARGETING (black-box, WAF-safe): cache_gap(base_url, endpoint) fuzzes path-normalization + static-extension variants for cache deception/poisoning; blind_oracle(base_url, param, value) detects which SINK a param reaches (sql/ssti/xss) via benign arithmetic (id=1+0, test${7*7}) WITHOUT a malicious payload; param_precedence(base_url, param, A, B) maps duplicate-parameter precedence (first/last-wins) for WAF-bypass. SOURCE TARGETING: action_surface(code) maps every wp_ajax_* action to its vuln class + DERIVED priority (what to look for WHERE); security_state(sanitizers, sink) gives a wrong-context sanitization verdict; framework_knowledge(framework) returns auth/nonce primitives for 9 frameworks; variant_scan(root, signature) mass-sweeps an install base for ONE bug family; patch_analyze(old, new) REVERSES a security patch into the 0-day, and its mine_signature feeds variant_scan to sweep unpatched copies. All of these are DETECTION HINTS — verify each live (strike_verify / browser_validate) before it enters the report. NEWEST DETECTORS — understand AND try them: variant_scan also emits priv_esc (privilege escalation — a role/capability/user change fed by request input, traced cross-file via reverse call-graph, e.g. set_role($id, sanitize_key($_POST['um-role'])) or update_user_meta(...,'wp_capabilities', $_POST[...])) and flags uploadAllow=>array('all') unrestricted-upload configs as file_upload (the file-manager/connector shape). TO TRY a priv_esc hit: submit the role field with 'administrator' (or send wp_capabilities meta) and confirm the account actually gains admin. TO TRY an unrestricted-upload hit: POST a .php/.phtml and confirm it lands web-reachable + executes. variant_scan also emits hardcoded_secret (CWE-798) in three tiers: a secret field (api_key/db_password/access_token/aws_*) assigned a literal (HIGH), a known secret FORMAT (JWT eyJ…/AWS AKIA…/GitHub ghp_…/Slack xoxb-…/…) regardless of name (HIGH), or a high-entropy suspect token (MEDIUM — verify before reporting). Verify a frontend/JS secret live via drive_devtools (inspect the JS bundle / network response and confirm the key is actually exposed), and for a backend secret confirm it is reachable/valid. A static hit is a HYPOTHESIS until verified live — never report unverified. For a repo, also scan_git_history(root) — secrets DELETED from HEAD still live in .git history (the removed-later-is-not-fixed trap), and it feeds every recovered pre-deletion blob through the same secret detector. Once you recover a credential, prove it is still ACTIVE with validate_leaked_key(apiBase, endpoints, key|blobUrl) — a READ-ONLY differential test (401-without-key vs 200-with-key = auth bypass PROVEN). Two supply-chain detectors: dependency_confusion (a manifest/build file resolving a package from a public registry — pypi.org/npmjs.org --extra-index-url, or a scoped @company/pkg with no private registry) and ml_supply_chain (torch.load without weights_only=True / joblib.load / np.load(allow_pickle=True) / keras load_model on an untrusted model → pickle RCE).\n" + `PRECISION ANALYSIS — chrome-devtools MCP is MANDATORY, not optional:
|
|
59600
59703
|
` + `- When a lead needs DOM/JS precision — DOM-XSS sink execution, AJAX endpoint + payload interception, JS runtime errors, redirect chains, SSO/token flow, or anything a static HTML glance cannot prove — call drive_devtools(target). It spawns chrome-devtools-mcp and drives a REAL headless browser (navigate -> list_network_requests -> list_console_messages -> evaluate_script), giving reproducible evidence instead of a guess.
|
|
59601
59704
|
` + `- Before calling it, check_mcp() to confirm the browser MCP is available; if not, blitzstrike install-tools or npm i -g chrome-devtools-mcp. Never substitute eyeballing minified JS or a static sink guess when a live browser can PROVE it. This is the precision + consistency layer.
|
|
59602
59705
|
` + "EXTERNAL MCP SERVERS (verified, connect them — NOT one-shot CLIs): chrome-devtools-mcp (29 tools: list_network_requests/get_network_request for raw HTTP interception, list_console_messages for JS errors + DOM-XSS, evaluate_script to run JS, take_screenshot) -> stdio chrome-devtools-mcp --headless --chromeArg=--no-sandbox --chromeArg=--disable-gpu (as root/container this is MANDATORY or the browser crashes; add --proxyServer http://127.0.0.1:8080 to route through Burp, --acceptInsecureCerts for bad TLS). burp-suite-mcp (proxy history + active scan + repeater) -> NOT npm: build the JAR (git clone https://github.com/PortSwigger/mcp-server.git && cd mcp-server && ./gradlew embedProxyJar), load it in Burp Extensions, then connect the client to http://127.0.0.1:9876 (SSE) or the stdio proxy java -jar mcp-proxy-all.jar --sse-url http://127.0.0.1:9876."
|
|
@@ -1,67 +1,325 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "Technique class -> CWE mapping (standard weakness IDs, for grounding + professional reporting). Each entry maps a techniques.json class id to its CWE ID(s) and name.",
|
|
3
3
|
"mapping": [
|
|
4
|
-
{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
{
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
{
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
{
|
|
65
|
-
|
|
4
|
+
{
|
|
5
|
+
"id": "ssrf",
|
|
6
|
+
"cwe": "CWE-918",
|
|
7
|
+
"name": "Server-Side Request Forgery (SSRF)"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"id": "request_smuggling",
|
|
11
|
+
"cwe": "CWE-444",
|
|
12
|
+
"name": "Inconsistent Interpretation of HTTP Requests (Request Smuggling)"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "cache_poisoning",
|
|
16
|
+
"cwe": "CWE-524",
|
|
17
|
+
"name": "Use of Cache Containing Sensitive Information"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"id": "race_condition",
|
|
21
|
+
"cwe": "CWE-362",
|
|
22
|
+
"name": "Concurrent Execution using Shared Resource (TOCTOU)"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "ssti",
|
|
26
|
+
"cwe": "CWE-1336",
|
|
27
|
+
"name": "Improper Neutralization of Special Elements Used in a Template Engine (SSTI)"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"id": "deserialization",
|
|
31
|
+
"cwe": "CWE-502",
|
|
32
|
+
"name": "Deserialization of Untrusted Data"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "prototype_pollution",
|
|
36
|
+
"cwe": "CWE-1321",
|
|
37
|
+
"name": "Improperly Controlled Modification of Object Prototype Attributes (Prototype Pollution)"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "mass_assignment",
|
|
41
|
+
"cwe": "CWE-915",
|
|
42
|
+
"name": "Improperly Controlled Modification of Dynamically-Determined Object Attributes"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "sql_injection",
|
|
46
|
+
"cwe": "CWE-89",
|
|
47
|
+
"name": "SQL Injection"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"id": "nosql_injection",
|
|
51
|
+
"cwe": "CWE-943",
|
|
52
|
+
"name": "Improper Neutralization of Special Elements in Data Query Logic (NoSQL Injection)"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": "xss",
|
|
56
|
+
"cwe": "CWE-79",
|
|
57
|
+
"name": "Cross-site Scripting"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "cors",
|
|
61
|
+
"cwe": "CWE-942",
|
|
62
|
+
"name": "Permissive Cross-domain Policy with Untrusted Domains (CORS)"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "csrf",
|
|
66
|
+
"cwe": "CWE-352",
|
|
67
|
+
"name": "Cross-Site Request Forgery"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "jwt",
|
|
71
|
+
"cwe": "CWE-347",
|
|
72
|
+
"name": "Improper Verification of Cryptographic Signature"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "oauth",
|
|
76
|
+
"cwe": "CWE-287",
|
|
77
|
+
"name": "Improper Authentication"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "host_header",
|
|
81
|
+
"cwe": "CWE-644",
|
|
82
|
+
"name": "Improper Neutralization of HTTP Headers for Scripting Syntax (Host Header)"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "open_redirect",
|
|
86
|
+
"cwe": "CWE-601",
|
|
87
|
+
"name": "URL Redirection to Untrusted Site (Open Redirect)"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "subdomain_takeover",
|
|
91
|
+
"cwe": "CWE-350",
|
|
92
|
+
"name": "Reliance on Reverse DNS Resolution for a Security-Critical Action"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"id": "idor",
|
|
96
|
+
"cwe": "CWE-639",
|
|
97
|
+
"name": "Authorization Bypass Through User-Controlled Key (IDOR/BOLA)"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"id": "graphql",
|
|
101
|
+
"cwe": "CWE-862",
|
|
102
|
+
"name": "Missing Authorization"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "websocket",
|
|
106
|
+
"cwe": "CWE-345",
|
|
107
|
+
"name": "Insufficient Verification of Data Authenticity (WebSocket Hijacking)"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "file_upload",
|
|
111
|
+
"cwe": "CWE-434",
|
|
112
|
+
"name": "Unrestricted Upload of File with Dangerous Type"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"id": "path_traversal_lfi",
|
|
116
|
+
"cwe": "CWE-22",
|
|
117
|
+
"name": "Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"id": "command_injection",
|
|
121
|
+
"cwe": "CWE-78",
|
|
122
|
+
"name": "OS Command Injection"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "xxe",
|
|
126
|
+
"cwe": "CWE-611",
|
|
127
|
+
"name": "Improper Restriction of XML External Entity Reference (XXE)"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"id": "crlf_injection",
|
|
131
|
+
"cwe": "CWE-93",
|
|
132
|
+
"name": "Improper Neutralization of CRLF Sequences (CRLF Injection)"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "ldap_injection",
|
|
136
|
+
"cwe": "CWE-90",
|
|
137
|
+
"name": "Improper Neutralization of Special Elements in LDAP Queries"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"id": "xpath_injection",
|
|
141
|
+
"cwe": "CWE-643",
|
|
142
|
+
"name": "Improper Neutralization of Data within XPath Expressions"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "xslt_injection",
|
|
146
|
+
"cwe": "CWE-91",
|
|
147
|
+
"name": "XML Injection (XSLT)"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
"id": "ssi_injection",
|
|
151
|
+
"cwe": "CWE-97",
|
|
152
|
+
"name": "Improper Neutralization of Server-Side Includes (SSI)"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"id": "xssi",
|
|
156
|
+
"cwe": "CWE-200",
|
|
157
|
+
"name": "Exposure of Sensitive Information to an Unauthorized Actor (XSSI)"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"id": "email_injection",
|
|
161
|
+
"cwe": "CWE-74",
|
|
162
|
+
"name": "Improper Neutralization of Special Elements in Output (Email Header Injection)"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "formula_csv_injection",
|
|
166
|
+
"cwe": "CWE-1236",
|
|
167
|
+
"name": "Improper Neutralization of Formula Elements in a CSV File"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"id": "orm_injection",
|
|
171
|
+
"cwe": "CWE-89",
|
|
172
|
+
"name": "SQL Injection (via ORM)"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"id": "rsql_injection",
|
|
176
|
+
"cwe": "CWE-89",
|
|
177
|
+
"name": "SQL Injection (RSQL/FIQL)"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"id": "unicode_injection",
|
|
181
|
+
"cwe": "CWE-180",
|
|
182
|
+
"name": "Incorrect Behavior Order: Validate Before Canonicalize"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"id": "dangling_markup",
|
|
186
|
+
"cwe": "CWE-79",
|
|
187
|
+
"name": "Cross-site Scripting (Dangling Markup)"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"id": "account_takeover",
|
|
191
|
+
"cwe": "CWE-287",
|
|
192
|
+
"name": "Improper Authentication (Account Takeover)"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"id": "two_fa_bypass",
|
|
196
|
+
"cwe": "CWE-308",
|
|
197
|
+
"name": "Use of Single-factor Authentication"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"id": "rate_limit_bypass",
|
|
201
|
+
"cwe": "CWE-799",
|
|
202
|
+
"name": "Improper Control of Interaction Frequency (Rate Limit)"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"id": "password_reset_bypass",
|
|
206
|
+
"cwe": "CWE-640",
|
|
207
|
+
"name": "Weak Password Recovery Mechanism for Forgotten Password"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "captcha_bypass",
|
|
211
|
+
"cwe": "CWE-804",
|
|
212
|
+
"name": "Guessable CAPTCHA"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"id": "registration_vulnerabilities",
|
|
216
|
+
"cwe": "CWE-799",
|
|
217
|
+
"name": "Improper Control of Interaction Frequency"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"id": "payment_bypass",
|
|
221
|
+
"cwe": "CWE-841",
|
|
222
|
+
"name": "Improper Enforcement of Behavioral Workflow (Business Logic)"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"id": "timing_attacks",
|
|
226
|
+
"cwe": "CWE-208",
|
|
227
|
+
"name": "Observable Timing Discrepancy"
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"id": "uuid_insecurities",
|
|
231
|
+
"cwe": "CWE-330",
|
|
232
|
+
"name": "Use of Insufficiently Random Values"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"id": "reverse_tab_nabbing",
|
|
236
|
+
"cwe": "CWE-1022",
|
|
237
|
+
"name": "Use of Web Link to Untrusted Target with window.opener Access (Reverse Tabnabbing)"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"id": "iframe_traps",
|
|
241
|
+
"cwe": "CWE-1021",
|
|
242
|
+
"name": "Improper Restriction of Rendered UI Layers or Frames (Clickjacking)"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"id": "cookie_hacking",
|
|
246
|
+
"cwe": "CWE-565",
|
|
247
|
+
"name": "Reliance on Cookies without Validation and Integrity Checking"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"id": "postmessage_vulnerabilities",
|
|
251
|
+
"cwe": "CWE-345",
|
|
252
|
+
"name": "Insufficient Verification of Data Authenticity (postMessage)"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"id": "web_vulnerabilities_methodology",
|
|
256
|
+
"cwe": "CWE-1057",
|
|
257
|
+
"name": "Improper Inventory / Methodology"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
"id": "missing_authz",
|
|
261
|
+
"cwe": "CWE-862",
|
|
262
|
+
"name": "Missing Authorization"
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"id": "missing_nonce",
|
|
266
|
+
"cwe": "CWE-352",
|
|
267
|
+
"name": "Cross-Site Request Forgery (Missing Nonce)"
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"id": "priv_esc",
|
|
271
|
+
"cwe": "CWE-269",
|
|
272
|
+
"name": "Improper Privilege Management"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"id": "hardcoded_secret",
|
|
276
|
+
"cwe": "CWE-798",
|
|
277
|
+
"name": "Use of Hard-coded Credentials"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"id": "type_juggling",
|
|
281
|
+
"cwe": "CWE-697",
|
|
282
|
+
"name": "Incorrect Comparison"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"id": "path_confusion",
|
|
286
|
+
"cwe": "CWE-22",
|
|
287
|
+
"name": "Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"id": "wrong_sanitizer",
|
|
291
|
+
"cwe": "CWE-20",
|
|
292
|
+
"name": "Improper Input Validation"
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"id": "llm_injection",
|
|
296
|
+
"cwe": "CWE-77",
|
|
297
|
+
"name": "Improper Neutralization of Special Elements used in a Command (LLM Prompt Injection)"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"id": "graphql_exposure",
|
|
301
|
+
"cwe": "CWE-200",
|
|
302
|
+
"name": "Exposure of Sensitive Information"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"id": "oauth_misconfig",
|
|
306
|
+
"cwe": "CWE-601",
|
|
307
|
+
"name": "URL Redirection to Untrusted Site (Open Redirect)"
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"id": "grpc_reflection",
|
|
311
|
+
"cwe": "CWE-200",
|
|
312
|
+
"name": "Exposure of Sensitive Information"
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"id": "dependency_confusion",
|
|
316
|
+
"cwe": "CWE-427",
|
|
317
|
+
"name": "Uncontrolled Search Path Element"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"id": "ml_supply_chain",
|
|
321
|
+
"cwe": "CWE-502",
|
|
322
|
+
"name": "Deserialization of Untrusted Data"
|
|
323
|
+
}
|
|
66
324
|
]
|
|
67
|
-
}
|
|
325
|
+
}
|