@clear-capabilities/agentic-security-scanner 0.77.0 → 0.78.0

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.
Files changed (83) hide show
  1. package/bin/.agentic-security/findings.json +1907 -0
  2. package/bin/.agentic-security/last-scan.json +1907 -0
  3. package/bin/.agentic-security/last-scan.json.sig +1 -0
  4. package/bin/.agentic-security/scan-history.json +115 -0
  5. package/bin/.agentic-security/streak.json +20 -0
  6. package/bin/agentic-security.js +33 -2
  7. package/dist/178.index.js +1 -1
  8. package/dist/384.index.js +1 -1
  9. package/dist/637.index.js +1 -1
  10. package/dist/718.index.js +106 -0
  11. package/dist/824.index.js +126 -0
  12. package/dist/838.index.js +1 -1
  13. package/dist/agentic-security.mjs +32 -32
  14. package/dist/agentic-security.mjs.sha256 +1 -1
  15. package/package.json +3 -3
  16. package/src/.agentic-security/findings.json +82642 -0
  17. package/src/.agentic-security/last-scan.json +82642 -0
  18. package/src/.agentic-security/last-scan.json.sig +1 -0
  19. package/src/.agentic-security/scan-history.json +10054 -0
  20. package/src/.agentic-security/streak.json +21 -0
  21. package/src/dataflow/.agentic-security/findings.json +3515 -0
  22. package/src/dataflow/.agentic-security/last-scan.json +3515 -0
  23. package/src/dataflow/.agentic-security/last-scan.json.sig +1 -0
  24. package/src/dataflow/.agentic-security/scan-history.json +702 -0
  25. package/src/dataflow/.agentic-security/streak.json +22 -0
  26. package/src/dataflow/async-sequencing.js +16 -7
  27. package/src/dataflow/builtin-summaries.js +131 -0
  28. package/src/dataflow/catalog.js +107 -0
  29. package/src/dataflow/cross-repo.js +75 -1
  30. package/src/dataflow/engine.js +129 -0
  31. package/src/dataflow/implicit-flow.js +24 -6
  32. package/src/dataflow/stub-aware-filter.js +69 -11
  33. package/src/dataflow/summaries.js +28 -3
  34. package/src/engine-parallel.js +70 -0
  35. package/src/engine.js +165 -15
  36. package/src/ir/.agentic-security/findings.json +3777 -0
  37. package/src/ir/.agentic-security/last-scan.json +3777 -0
  38. package/src/ir/.agentic-security/last-scan.json.sig +1 -0
  39. package/src/ir/.agentic-security/scan-history.json +771 -0
  40. package/src/ir/.agentic-security/streak.json +21 -0
  41. package/src/ir/index.js +22 -1
  42. package/src/ir/parser-go.js +403 -0
  43. package/src/ir/parser-js.js +2 -0
  44. package/src/ir/parser-php.js +330 -0
  45. package/src/ir/parser-py.helper.py +137 -11
  46. package/src/ir/parser-rb.js +309 -0
  47. package/src/posture/.agentic-security/findings.json +51562 -0
  48. package/src/posture/.agentic-security/last-scan.json +51562 -0
  49. package/src/posture/.agentic-security/last-scan.json.sig +1 -0
  50. package/src/posture/.agentic-security/scan-history.json +650 -0
  51. package/src/posture/.agentic-security/streak.json +20 -0
  52. package/src/posture/calibration.js +14 -0
  53. package/src/posture/triage.js +13 -0
  54. package/src/report/.agentic-security/findings.json +80 -0
  55. package/src/report/.agentic-security/last-scan.json +80 -0
  56. package/src/report/.agentic-security/last-scan.json.sig +1 -0
  57. package/src/report/.agentic-security/scan-history.json +35 -0
  58. package/src/report/.agentic-security/streak.json +22 -0
  59. package/src/report/index.js +23 -2
  60. package/src/sast/.agentic-security/findings.json +5190 -0
  61. package/src/sast/.agentic-security/last-scan.json +5190 -0
  62. package/src/sast/.agentic-security/last-scan.json.sig +1 -0
  63. package/src/sast/.agentic-security/scan-history.json +408 -0
  64. package/src/sast/.agentic-security/streak.json +20 -0
  65. package/src/sast/cache-poisoning.js +77 -0
  66. package/src/sast/comparison-safety.js +73 -0
  67. package/src/sast/db-taint.js +54 -0
  68. package/src/sast/graphql.js +127 -0
  69. package/src/sast/llm-stored-prompt.js +57 -0
  70. package/src/sast/mutation-xss.js +43 -0
  71. package/src/sast/nosql-injection.js +5 -0
  72. package/src/sast/null-byte-injection.js +76 -0
  73. package/src/sast/redos-nfa.js +338 -0
  74. package/src/sast/sensitive-data-logging.js +73 -0
  75. package/src/sast/weak-password-hash.js +77 -0
  76. package/src/sast/weak-randomness.js +100 -0
  77. package/src/sca/.agentic-security/findings.json +1587 -0
  78. package/src/sca/.agentic-security/last-scan.json +1587 -0
  79. package/src/sca/.agentic-security/last-scan.json.sig +1 -0
  80. package/src/sca/.agentic-security/scan-history.json +36 -0
  81. package/src/sca/.agentic-security/streak.json +21 -0
  82. package/src/sca/llm-function-extract.js +107 -0
  83. package/src/sca/vendor-detect.js +91 -0
@@ -0,0 +1 @@
1
+ 1a7a7e91a1b09ea956d4e722c3d9df15e8c662dba64e487bdc6f8ba875fd48b9
@@ -0,0 +1,115 @@
1
+ [
2
+ {
3
+ "timestamp": "2026-05-26T04:00:10.464Z",
4
+ "label": "scan",
5
+ "total": 4,
6
+ "critical": 0,
7
+ "high": 0,
8
+ "medium": 4,
9
+ "low": 0,
10
+ "kev": 0,
11
+ "ids": [
12
+ "toctou-fs:agentic-security-audit.js:55",
13
+ "toctou-fs:agentic-security-consistency.js:44",
14
+ "toctou-fs:agentic-security-consistency.js:66",
15
+ "toctou-fs:agentic-security.js:1108"
16
+ ]
17
+ },
18
+ {
19
+ "timestamp": "2026-05-26T04:00:56.905Z",
20
+ "label": "scan",
21
+ "total": 4,
22
+ "critical": 0,
23
+ "high": 0,
24
+ "medium": 4,
25
+ "low": 0,
26
+ "kev": 0,
27
+ "ids": [
28
+ "toctou-fs:agentic-security-audit.js:55",
29
+ "toctou-fs:agentic-security-consistency.js:44",
30
+ "toctou-fs:agentic-security-consistency.js:66",
31
+ "toctou-fs:agentic-security.js:1108"
32
+ ]
33
+ },
34
+ {
35
+ "timestamp": "2026-05-26T04:02:41.681Z",
36
+ "label": "scan",
37
+ "total": 4,
38
+ "critical": 0,
39
+ "high": 0,
40
+ "medium": 4,
41
+ "low": 0,
42
+ "kev": 0,
43
+ "ids": [
44
+ "toctou-fs:agentic-security-audit.js:55",
45
+ "toctou-fs:agentic-security-consistency.js:44",
46
+ "toctou-fs:agentic-security-consistency.js:66",
47
+ "toctou-fs:agentic-security.js:1108"
48
+ ]
49
+ },
50
+ {
51
+ "timestamp": "2026-05-27T01:03:34.318Z",
52
+ "label": "scan",
53
+ "total": 4,
54
+ "critical": 0,
55
+ "high": 0,
56
+ "medium": 4,
57
+ "low": 0,
58
+ "kev": 0,
59
+ "ids": [
60
+ "toctou-fs:agentic-security-audit.js:55",
61
+ "toctou-fs:agentic-security-consistency.js:44",
62
+ "toctou-fs:agentic-security-consistency.js:66",
63
+ "toctou-fs:agentic-security.js:1109"
64
+ ]
65
+ },
66
+ {
67
+ "timestamp": "2026-05-27T01:05:45.968Z",
68
+ "label": "scan",
69
+ "total": 4,
70
+ "critical": 0,
71
+ "high": 0,
72
+ "medium": 4,
73
+ "low": 0,
74
+ "kev": 0,
75
+ "ids": [
76
+ "toctou-fs:agentic-security-audit.js:55",
77
+ "toctou-fs:agentic-security-consistency.js:44",
78
+ "toctou-fs:agentic-security-consistency.js:66",
79
+ "toctou-fs:agentic-security.js:1114"
80
+ ]
81
+ },
82
+ {
83
+ "timestamp": "2026-05-27T11:21:25.101Z",
84
+ "label": "scan",
85
+ "total": 4,
86
+ "critical": 0,
87
+ "high": 0,
88
+ "medium": 4,
89
+ "low": 0,
90
+ "kev": 0,
91
+ "ids": [
92
+ "toctou-fs:agentic-security-audit.js:55",
93
+ "toctou-fs:agentic-security-consistency.js:44",
94
+ "toctou-fs:agentic-security-consistency.js:66",
95
+ "toctou-fs:agentic-security.js:1116"
96
+ ]
97
+ },
98
+ {
99
+ "timestamp": "2026-05-27T11:23:11.242Z",
100
+ "label": "scan",
101
+ "total": 5,
102
+ "critical": 0,
103
+ "high": 0,
104
+ "medium": 5,
105
+ "low": 0,
106
+ "kev": 0,
107
+ "ids": [
108
+ "toctou-fs:agentic-security-audit.js:55",
109
+ "toctou-fs:agentic-security-consistency.js:44",
110
+ "toctou-fs:agentic-security-consistency.js:66",
111
+ "toctou-fs:agentic-security.js:1136",
112
+ "toctou-fs:agentic-security.js:362"
113
+ ]
114
+ }
115
+ ]
@@ -0,0 +1,20 @@
1
+ {
2
+ "firstScanDate": "2026-05-26T04:00:10.482Z",
3
+ "lastScanDate": "2026-05-27T11:23:11.268Z",
4
+ "totalScans": 7,
5
+ "daysCleanCritical": 2,
6
+ "lastCleanDate": "2026-05-27",
7
+ "lastCriticalDate": null,
8
+ "hasEverHadCritical": false,
9
+ "bestDaysCleanCritical": 2,
10
+ "totalFindingsAtFirstScan": 11,
11
+ "totalFindingsAtLastScan": 13,
12
+ "totalFixesInferred": 0,
13
+ "lastGrade": "A-",
14
+ "bestGrade": "A-",
15
+ "launchCheckPassedAt": null,
16
+ "achievements": [
17
+ "first-scan"
18
+ ],
19
+ "previousGrade": "A-"
20
+ }
@@ -4,6 +4,9 @@
4
4
  import * as fs from 'node:fs';
5
5
  import * as fsp from 'node:fs/promises';
6
6
  import * as path from 'node:path';
7
+ import { createRequire } from 'node:module';
8
+ const __require = createRequire(import.meta.url);
9
+ const PKG_VERSION = __require('../package.json').version;
7
10
  import { signLastScan as _signLastScan, verifyLastScan as _verifyLastScanShared } from '../src/posture/integrity.js';
8
11
  import { runScan } from '../src/runScan.js';
9
12
  import { toJSON, toMarkdown, toSARIF, toSTIX, toCSV, toJUnit, toCLI, toCLIByProfile, toShipVerdict, toProTable, toHTML, toSummary, exitCodeFor, normalizeFindings } from '../src/report/index.js';
@@ -103,6 +106,9 @@ Options:
103
106
  --no-network Skip OSV/registry queries (offline mode)
104
107
  --pr [ref] Diff-aware: scan only files changed since ref (auto-detects PR base)
105
108
  --deterministic Reproducible scan: stable sort, no-network, lockfile-checked
109
+ --incremental Reuse taint summaries from prior scans (speeds up deep mode in CI)
110
+ --set-baseline Save current findings as baseline (suppresses pre-existing issues)
111
+ --since-baseline Only show findings NOT in the saved baseline
106
112
  --no-epss Skip EPSS exploit-prediction enrichment (default: enabled)
107
113
  --no-blast-radius Skip blast-radius / cost framing (default: enabled)
108
114
  --verbose Include fix bodies + taxonomy in CLI output
@@ -137,7 +143,7 @@ function printBanner(args) {
137
143
  BOLD: '\x1b[1m',
138
144
  RESET: '\x1b[0m',
139
145
  } : { FROG:'', DEEP:'', CREAM:'', DIM:'', BOLD:'', RESET:'' };
140
- const v = '0.75.1';
146
+ const v = PKG_VERSION;
141
147
  const compact = !args.flags.full;
142
148
  if (compact) {
143
149
  const lines = [
@@ -314,6 +320,11 @@ async function cmdScan(args) {
314
320
  }
315
321
  }
316
322
 
323
+ // --incremental : reuse taint summaries from prior scans for faster deep mode.
324
+ if (args.flags['incremental'] || process.env.AGENTIC_SECURITY_INCREMENTAL === '1') {
325
+ process.env.AGENTIC_SECURITY_INCREMENTAL = '1';
326
+ }
327
+
317
328
  // --pr [ref] : friendlier alias for --changed-since that auto-detects the PR
318
329
  // base ref (GitHub/GitLab/Buildkite/Bitbucket env vars) when no value is given.
319
330
  let changedSince = args.flags['changed-since'] || null;
@@ -338,6 +349,26 @@ async function cmdScan(args) {
338
349
  if (only === 'secrets') { scan.findings = []; scan.supplyChain = []; }
339
350
  }
340
351
 
352
+ // --set-baseline: save current findings as baseline for future --since-baseline filtering
353
+ const baselinePath = path.join(target || '.', '.agentic-security', 'baseline.json');
354
+ if (args.flags['set-baseline']) {
355
+ const { normalizeFindings } = await import('../src/report/index.js');
356
+ const baselineIds = new Set(normalizeFindings(scan).map(f => f.stableId || f.id));
357
+ fs.mkdirSync(path.dirname(baselinePath), { recursive: true });
358
+ fs.writeFileSync(baselinePath, JSON.stringify({ ids: [...baselineIds], createdAt: new Date().toISOString(), count: baselineIds.size }, null, 2));
359
+ process.stderr.write(`[baseline] saved ${baselineIds.size} findings as baseline\n`);
360
+ }
361
+ // --since-baseline: filter out findings that existed in the saved baseline
362
+ if (args.flags['since-baseline'] && fs.existsSync(baselinePath)) {
363
+ try {
364
+ const baseline = JSON.parse(fs.readFileSync(baselinePath, 'utf8'));
365
+ const baselineSet = new Set(baseline.ids || []);
366
+ const before = scan.findings.length;
367
+ scan.findings = (scan.findings || []).filter(f => !baselineSet.has(f.stableId || f.id));
368
+ process.stderr.write(`[baseline] filtered ${before - scan.findings.length} baseline findings, ${scan.findings.length} new\n`);
369
+ } catch { /* baseline file unreadable, skip */ }
370
+ }
371
+
341
372
  // 0.9.0 Feat-18: --scorecard flag enables OSSF Scorecard enrichment
342
373
  if (args.flags['scorecard']) process.env.AGENTIC_SECURITY_SCORECARD = '1';
343
374
 
@@ -1665,7 +1696,7 @@ async function main() {
1665
1696
  }
1666
1697
  process.exit(0);
1667
1698
  }
1668
- case 'version': console.log('agentic-security 0.75.1 · created by ClearCapabilities.Com'); process.exit(0);
1699
+ case 'version': console.log(`agentic-security ${PKG_VERSION} · created by ClearCapabilities.Com`); process.exit(0);
1669
1700
  case 'banner': { printBanner(args); process.exit(0); }
1670
1701
  case 'harness': process.exit(await cmdHarness(args));
1671
1702
  case 'scan-baseline': process.exit(await cmdScanBaseline(args));
package/dist/178.index.js CHANGED
@@ -13,7 +13,7 @@ export const modules = {
13
13
  /* harmony import */ var node_child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1421);
14
14
  /* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3024);
15
15
  /* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6760);
16
- /* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3291);
16
+ /* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8636);
17
17
  // Time-travel + counterfactual scanning (v0.68).
18
18
  //
19
19
  // Two new modes that exploit the pure-input shape of runFullScan:
package/dist/384.index.js CHANGED
@@ -8,7 +8,7 @@ export const modules = {
8
8
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9
9
  /* harmony export */ scanCredentials: () => (/* reexport safe */ _engine_js__WEBPACK_IMPORTED_MODULE_0__.Sv)
10
10
  /* harmony export */ });
11
- /* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3291);
11
+ /* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(8636);
12
12
  // Secrets submodule view of the engine — credential + entropy + TODO scanning.
13
13
 
14
14
 
package/dist/637.index.js CHANGED
@@ -10,7 +10,7 @@ export const modules = {
10
10
  /* harmony export */ renderPrDeltaText: () => (/* binding */ renderPrDeltaText)
11
11
  /* harmony export */ });
12
12
  /* harmony import */ var node_child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1421);
13
- /* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3291);
13
+ /* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8636);
14
14
  // Shadowscan / security-DELTA on PR (v0.72).
15
15
  //
16
16
  // Most SAST PR-comment integrations show absolute counts — "12 findings
@@ -0,0 +1,106 @@
1
+ export const id = 718;
2
+ export const ids = [718];
3
+ export const modules = {
4
+
5
+ /***/ 8718:
6
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
7
+
8
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9
+ /* harmony export */ detectVendoredLibraries: () => (/* binding */ detectVendoredLibraries)
10
+ /* harmony export */ });
11
+ // Vendored / copied library detection via version-string fingerprinting.
12
+ //
13
+ // Detects library code copied into src/ that bypasses SCA. Uses version
14
+ // string patterns (_.VERSION, jQuery.fn.jquery, etc.) and characteristic
15
+ // function signatures to identify vendored libraries.
16
+
17
+ const VERSION_FINGERPRINTS = [
18
+ { pkg: 'lodash', ecosystem: 'npm', patterns: [
19
+ { re: /\b(?:lodash|_)\.VERSION\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
20
+ { re: /\b__lodash_hash_undefined__\b/, version: null },
21
+ ]},
22
+ { pkg: 'jquery', ecosystem: 'npm', patterns: [
23
+ { re: /jQuery\.fn\.jquery\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
24
+ { re: /\bjQuery\.fn\.init\b/, version: null },
25
+ ]},
26
+ { pkg: 'underscore', ecosystem: 'npm', patterns: [
27
+ { re: /\b_\.VERSION\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
28
+ ]},
29
+ { pkg: 'moment', ecosystem: 'npm', patterns: [
30
+ { re: /\bmoment\.version\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
31
+ { re: /\bmoment\.(?:utc|parseZone|duration|locale)\b/, version: null },
32
+ ]},
33
+ { pkg: 'handlebars', ecosystem: 'npm', patterns: [
34
+ { re: /\bHandlebars\.VERSION\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
35
+ ]},
36
+ { pkg: 'backbone', ecosystem: 'npm', patterns: [
37
+ { re: /\bBackbone\.VERSION\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
38
+ ]},
39
+ { pkg: 'angular', ecosystem: 'npm', patterns: [
40
+ { re: /\bangular\.version\s*=\s*\{[^}]*full\s*:\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
41
+ ]},
42
+ { pkg: 'vue', ecosystem: 'npm', patterns: [
43
+ { re: /\bVue\.version\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
44
+ ]},
45
+ { pkg: 'react', ecosystem: 'npm', patterns: [
46
+ { re: /\bReactVersion\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
47
+ ]},
48
+ { pkg: 'dompurify', ecosystem: 'npm', patterns: [
49
+ { re: /\bDOMPurify\.version\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
50
+ ]},
51
+ { pkg: 'marked', ecosystem: 'npm', patterns: [
52
+ { re: /\bmarked\.(?:defaults|setOptions|use|parse)\b[\s\S]{0,200}version\s*[:=]\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
53
+ ]},
54
+ { pkg: 'axios', ecosystem: 'npm', patterns: [
55
+ { re: /\baxios\.VERSION\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
56
+ ]},
57
+ { pkg: 'socket.io-client', ecosystem: 'npm', patterns: [
58
+ { re: /\bio\.protocol\s*=\s*(\d+)/, version: null },
59
+ ]},
60
+ { pkg: 'highlight.js', ecosystem: 'npm', patterns: [
61
+ { re: /\bhljs\.versionString\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
62
+ ]},
63
+ { pkg: 'chart.js', ecosystem: 'npm', patterns: [
64
+ { re: /\bChart\.version\s*=\s*['"](\d+\.\d+\.\d+)['"]/, versionGroup: 1 },
65
+ ]},
66
+ ];
67
+
68
+ const SKIP_DIRS = /(?:^|[/\\])(?:node_modules|vendor|dist|build|\.next|__pycache__|\.git)[/\\]/;
69
+
70
+ function detectVendoredLibraries(fileContents) {
71
+ if (!fileContents || typeof fileContents !== 'object') return [];
72
+ const detected = [];
73
+ const seen = new Set();
74
+
75
+ for (const [fp, content] of Object.entries(fileContents)) {
76
+ if (!content || typeof content !== 'string') continue;
77
+ if (SKIP_DIRS.test(fp)) continue;
78
+ if (content.length < 500) continue;
79
+
80
+ for (const lib of VERSION_FINGERPRINTS) {
81
+ for (const pat of lib.patterns) {
82
+ const m = content.match(pat.re);
83
+ if (!m) continue;
84
+ const version = pat.versionGroup ? m[pat.versionGroup] : null;
85
+ const key = `${lib.pkg}:${fp}`;
86
+ if (seen.has(key)) continue;
87
+ seen.add(key);
88
+ detected.push({
89
+ name: lib.pkg,
90
+ version: version || 'unknown',
91
+ ecosystem: lib.ecosystem,
92
+ file: fp,
93
+ scope: 'vendored',
94
+ isVendored: true,
95
+ });
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ return detected;
101
+ }
102
+
103
+
104
+ /***/ })
105
+
106
+ };
@@ -0,0 +1,126 @@
1
+ export const id = 824;
2
+ export const ids = [824];
3
+ export const modules = {
4
+
5
+ /***/ 9824:
6
+ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
7
+
8
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9
+ /* harmony export */ extractVulnFunctionsViaLLM: () => (/* binding */ extractVulnFunctionsViaLLM)
10
+ /* harmony export */ });
11
+ /* unused harmony export isLlmScaEnabled */
12
+ /* harmony import */ var node_crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7598);
13
+ /* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3024);
14
+ /* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6760);
15
+ // LLM-assisted vulnerable function extraction for SCA findings.
16
+ //
17
+ // For CVEs without OSV ecosystem_specific data or GHSA fix commits,
18
+ // uses an LLM to extract vulnerable function names from the CVE description.
19
+ //
20
+ // Gated behind AGENTIC_SECURITY_LLM_SCA=1 (opt-in).
21
+ // Uses the same LLM endpoint config as the SAST validator.
22
+
23
+
24
+
25
+
26
+
27
+ const CACHE_DIR = process.env.XDG_CONFIG_HOME
28
+ ? node_path__WEBPACK_IMPORTED_MODULE_2__.join(process.env.XDG_CONFIG_HOME, 'agentic-security', 'llm-sca-cache')
29
+ : node_path__WEBPACK_IMPORTED_MODULE_2__.join(process.env.HOME || '/tmp', '.config', 'agentic-security', 'llm-sca-cache');
30
+
31
+ function _cacheKey(osvId) {
32
+ return node_crypto__WEBPACK_IMPORTED_MODULE_0__.createHash('sha256').update(`sca-fn:${osvId}`).digest('hex').slice(0, 16);
33
+ }
34
+
35
+ function _readCache(osvId) {
36
+ try {
37
+ const fp = node_path__WEBPACK_IMPORTED_MODULE_2__.join(CACHE_DIR, _cacheKey(osvId) + '.json');
38
+ return JSON.parse(node_fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync(fp, 'utf8'));
39
+ } catch { return null; }
40
+ }
41
+
42
+ function _writeCache(osvId, data) {
43
+ try {
44
+ node_fs__WEBPACK_IMPORTED_MODULE_1__.mkdirSync(CACHE_DIR, { recursive: true });
45
+ node_fs__WEBPACK_IMPORTED_MODULE_1__.writeFileSync(node_path__WEBPACK_IMPORTED_MODULE_2__.join(CACHE_DIR, _cacheKey(osvId) + '.json'), JSON.stringify(data));
46
+ } catch { /* cache write failure is non-fatal */ }
47
+ }
48
+
49
+ function isLlmScaEnabled() {
50
+ return process.env.AGENTIC_SECURITY_LLM_SCA === '1';
51
+ }
52
+
53
+ function _endpointConfig() {
54
+ const endpoint = process.env.AGENTIC_SECURITY_LLM_ENDPOINT;
55
+ const apiKey = process.env.AGENTIC_SECURITY_LLM_API_KEY;
56
+ const model = process.env.AGENTIC_SECURITY_LLM_MODEL || 'unknown';
57
+ return endpoint ? { endpoint, apiKey, model } : null;
58
+ }
59
+
60
+ async function _askLlm(prompt, config) {
61
+ const headers = { 'Content-Type': 'application/json' };
62
+ if (config.apiKey) headers['Authorization'] = `Bearer ${config.apiKey}`;
63
+ const resp = await fetch(config.endpoint, {
64
+ method: 'POST',
65
+ headers,
66
+ body: JSON.stringify({ prompt, model: config.model }),
67
+ signal: AbortSignal.timeout(15000),
68
+ });
69
+ if (!resp.ok) return null;
70
+ const text = await resp.text();
71
+ const jsonMatch = text.match(/\{[^{}]*"functions"\s*:\s*\[[^\]]*\][^{}]*\}/);
72
+ if (!jsonMatch) return null;
73
+ try { return JSON.parse(jsonMatch[0]); } catch { return null; }
74
+ }
75
+
76
+ async function extractVulnFunctionsViaLLM(supplyChain, opts = {}) {
77
+ if (!isLlmScaEnabled()) return [];
78
+ const config = _endpointConfig();
79
+ if (!config) return [];
80
+
81
+ const enriched = [];
82
+ const candidates = (supplyChain || []).filter(sc =>
83
+ sc.type === 'vulnerable_dep' &&
84
+ (!sc.osvVulnFunctions || !sc.osvVulnFunctions.length) &&
85
+ sc.noKnownCallSite &&
86
+ sc.description
87
+ );
88
+
89
+ const BATCH_LIMIT = 20;
90
+ for (const sc of candidates.slice(0, BATCH_LIMIT)) {
91
+ const cached = _readCache(sc.osvId);
92
+ if (cached) {
93
+ if (cached.functions && cached.functions.length) {
94
+ sc.osvVulnFunctions = cached.functions;
95
+ sc._llmFunctionExtracted = true;
96
+ enriched.push(sc);
97
+ }
98
+ continue;
99
+ }
100
+
101
+ const prompt = `Given security advisory ${sc.osvId || ''} (${sc.cveAliases?.[0] || ''}) affecting npm package "${sc.name}" version ${sc.version}:\n\nDescription: ${sc.description.slice(0, 500)}\n\nWhat specific exported function(s) in this package are vulnerable? Return ONLY a JSON object: { "functions": ["functionName1", "functionName2"] }\n\nIf you cannot determine the specific functions, return: { "functions": [] }`;
102
+
103
+ try {
104
+ const result = await _askLlm(prompt, config);
105
+ if (result && Array.isArray(result.functions)) {
106
+ const fns = result.functions.filter(f => typeof f === 'string' && f.length > 0 && f.length < 100);
107
+ _writeCache(sc.osvId, { functions: fns, model: config.model, extractedAt: new Date().toISOString() });
108
+ if (fns.length) {
109
+ sc.osvVulnFunctions = fns;
110
+ sc._llmFunctionExtracted = true;
111
+ enriched.push(sc);
112
+ }
113
+ } else {
114
+ _writeCache(sc.osvId, { functions: [], model: config.model, extractedAt: new Date().toISOString() });
115
+ }
116
+ } catch {
117
+ // LLM call failure — skip, don't cache (may be transient)
118
+ }
119
+ }
120
+ return enriched;
121
+ }
122
+
123
+
124
+ /***/ })
125
+
126
+ };
package/dist/838.index.js CHANGED
@@ -14,7 +14,7 @@ __webpack_require__.r(__webpack_exports__);
14
14
  /* harmony import */ var node_child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1421);
15
15
  /* harmony import */ var node_fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3024);
16
16
  /* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6760);
17
- /* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3291);
17
+ /* harmony import */ var _engine_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8636);
18
18
  // Closed-loop /fix verification (Sentinel-parity FR-L4-4, FR-L4-5).
19
19
  //
20
20
  // Given a candidate patch (the new file content + the finding stableId being