@clear-capabilities/agentic-security-scanner 0.172.0 → 0.173.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 (202) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/bin/agentic-security.js +37 -0
  3. package/dist/119.index.js +197 -0
  4. package/dist/128.index.js +129 -0
  5. package/dist/1293.index.js +5689 -0
  6. package/dist/1336.index.js +101 -101
  7. package/dist/1351.index.js +133 -0
  8. package/dist/1387.index.js +271 -0
  9. package/dist/1437.index.js +23 -0
  10. package/dist/1445.index.js +110 -0
  11. package/dist/1505.index.js +151 -0
  12. package/dist/1557.index.js +293 -0
  13. package/dist/1621.index.js +311 -0
  14. package/dist/1751.index.js +160 -0
  15. package/dist/1765.index.js +727 -0
  16. package/dist/1861.index.js +690 -0
  17. package/dist/1898.index.js +116 -0
  18. package/dist/1906.index.js +433 -0
  19. package/dist/1920.index.js +1 -291
  20. package/dist/208.index.js +1631 -0
  21. package/dist/2199.index.js +0 -239
  22. package/dist/2223.index.js +159 -0
  23. package/dist/2530.index.js +152 -0
  24. package/dist/2565.index.js +116 -0
  25. package/dist/2574.index.js +127 -0
  26. package/dist/2620.index.js +345 -0
  27. package/dist/2773.index.js +98 -0
  28. package/dist/2775.index.js +32 -0
  29. package/dist/2966.index.js +171 -0
  30. package/dist/2972.index.js +87 -0
  31. package/dist/2991.index.js +131 -0
  32. package/dist/3063.index.js +833 -0
  33. package/dist/3075.index.js +227 -0
  34. package/dist/3121.index.js +297 -0
  35. package/dist/3314.index.js +263 -0
  36. package/dist/3480.index.js +1822 -0
  37. package/dist/3481.index.js +24 -0
  38. package/dist/3506.index.js +268 -0
  39. package/dist/3533.index.js +591 -0
  40. package/dist/3653.index.js +450 -0
  41. package/dist/3822.index.js +131 -0
  42. package/dist/3868.index.js +292 -0
  43. package/dist/3917.index.js +152 -0
  44. package/dist/3918.index.js +192 -0
  45. package/dist/4090.index.js +288 -0
  46. package/dist/4121.index.js +1190 -0
  47. package/dist/4142.index.js +0 -239
  48. package/dist/4336.index.js +436 -0
  49. package/dist/4387.index.js +532 -0
  50. package/dist/4413.index.js +302 -0
  51. package/dist/4476.index.js +4510 -0
  52. package/dist/4491.index.js +133 -0
  53. package/dist/4538.index.js +185 -0
  54. package/dist/4684.index.js +319 -0
  55. package/dist/4740.index.js +165 -0
  56. package/dist/4780.index.js +209 -0
  57. package/dist/4802.index.js +225 -0
  58. package/dist/4812.index.js +379 -0
  59. package/dist/4835.index.js +126 -0
  60. package/dist/494.index.js +226 -0
  61. package/dist/4991.index.js +549 -0
  62. package/dist/5199.index.js +305 -0
  63. package/dist/5216.index.js +109 -0
  64. package/dist/5439.index.js +301 -0
  65. package/dist/5443.index.js +97 -0
  66. package/dist/5496.index.js +377 -0
  67. package/dist/550.index.js +2 -1
  68. package/dist/5801.index.js +588 -0
  69. package/dist/5858.index.js +223 -0
  70. package/dist/5933.index.js +143 -0
  71. package/dist/601.index.js +23 -0
  72. package/dist/6173.index.js +273 -0
  73. package/dist/6291.index.js +1871 -0
  74. package/dist/6312.index.js +666 -0
  75. package/dist/634.index.js +16182 -0
  76. package/dist/644.index.js +87 -0
  77. package/dist/6508.index.js +283 -0
  78. package/dist/6560.index.js +645 -0
  79. package/dist/6576.index.js +422 -0
  80. package/dist/6579.index.js +271 -0
  81. package/dist/6745.index.js +305 -0
  82. package/dist/6818.index.js +21642 -0
  83. package/dist/6972.index.js +167 -0
  84. package/dist/6995.index.js +163 -0
  85. package/dist/7249.index.js +191 -0
  86. package/dist/7372.index.js +1197 -0
  87. package/dist/7405.index.js +23 -6
  88. package/dist/7546.index.js +541 -0
  89. package/dist/76.index.js +448 -0
  90. package/dist/7879.index.js +163 -0
  91. package/dist/8025.index.js +130 -0
  92. package/dist/8054.index.js +248 -0
  93. package/dist/8097.index.js +201 -0
  94. package/dist/8126.index.js +191 -0
  95. package/dist/8178.index.js +78 -0
  96. package/dist/818.index.js +212 -0
  97. package/dist/8382.index.js +93 -0
  98. package/dist/8408.index.js +261 -0
  99. package/dist/8540.index.js +174 -0
  100. package/dist/8635.index.js +802 -0
  101. package/dist/8688.index.js +410 -0
  102. package/dist/8699.index.js +779 -0
  103. package/dist/8891.index.js +457 -0
  104. package/dist/8916.index.js +885 -0
  105. package/dist/9146.index.js +170 -0
  106. package/dist/9168.index.js +841 -0
  107. package/dist/9292.index.js +369 -0
  108. package/dist/9382.index.js +338 -48
  109. package/dist/9422.index.js +866 -0
  110. package/dist/9440.index.js +453 -0
  111. package/dist/9479.index.js +152 -0
  112. package/dist/9481.index.js +220 -0
  113. package/dist/9539.index.js +100 -0
  114. package/dist/9547.index.js +103 -0
  115. package/dist/9560.index.js +41 -61
  116. package/dist/9692.index.js +90 -0
  117. package/dist/9800.index.js +213 -1
  118. package/dist/9899.index.js +138 -0
  119. package/dist/9981.index.js +206 -0
  120. package/dist/999.index.js +117 -0
  121. package/dist/agentic-security.mjs +28 -28
  122. package/dist/agentic-security.mjs.sha256 +1 -1
  123. package/package.json +31 -6
  124. package/src/context-intelligence/CLAUDE.md +4 -0
  125. package/src/context-intelligence/adapters/haskell-hie.js +28 -1
  126. package/src/context-intelligence/candidates.js +2 -1
  127. package/src/context-intelligence/canonical.js +25 -0
  128. package/src/context-intelligence/capabilities.js +2 -1
  129. package/src/context-intelligence/cli.js +16 -10
  130. package/src/context-intelligence/config.js +4 -1
  131. package/src/context-intelligence/controls.js +108 -10
  132. package/src/context-intelligence/counterexample.js +200 -0
  133. package/src/context-intelligence/cross-route.js +111 -0
  134. package/src/context-intelligence/entrypoints.js +2 -2
  135. package/src/context-intelligence/evaluation/index.js +11 -4
  136. package/src/context-intelligence/evaluation/scripted-reader.js +12 -2
  137. package/src/context-intelligence/findings.js +166 -0
  138. package/src/context-intelligence/invariants.js +197 -0
  139. package/src/context-intelligence/queue.js +6 -1
  140. package/src/context-intelligence/reachability.js +10 -4
  141. package/src/context-intelligence/review.js +129 -16
  142. package/src/dataflow/access-paths.js +11 -0
  143. package/src/dataflow/analysis-limits.js +66 -0
  144. package/src/dataflow/engine.js +272 -20
  145. package/src/dataflow/service-edges.js +174 -0
  146. package/src/dataflow/summaries.js +7 -1
  147. package/src/discovery/judge.js +2 -1
  148. package/src/engine.js +82 -14
  149. package/src/fix/apply-fix-service.js +55 -8
  150. package/src/fix/batch-journal.js +84 -0
  151. package/src/fix/exploit-replay.js +51 -0
  152. package/src/fix/footprint.js +65 -0
  153. package/src/fix/patch-policy.js +49 -0
  154. package/src/fix/secret-persistence.js +39 -0
  155. package/src/fix/test-commands.js +84 -0
  156. package/src/fix/verification-adapters.js +97 -0
  157. package/src/fix/verification-record.js +243 -0
  158. package/src/fix/verify-patch.js +89 -0
  159. package/src/ir/CLAUDE.md +5 -0
  160. package/src/ir/callgraph.js +23 -1
  161. package/src/ir/module-resolver.js +315 -0
  162. package/src/ir/parser-js.js +21 -2
  163. package/src/ir/semantic-graph.js +245 -0
  164. package/src/lineage/build-attested-correlation.js +63 -0
  165. package/src/lineage/deployment-identity.js +76 -0
  166. package/src/mcp/tools.js +13 -34
  167. package/src/pipeline/canonical-output.js +64 -0
  168. package/src/pipeline/detector-runner.js +7 -0
  169. package/src/pipeline/scan-health.js +14 -0
  170. package/src/pipeline/supervised-analyzers.js +125 -0
  171. package/src/pipeline/supervised-child.js +17 -0
  172. package/src/pipeline/telemetry.js +79 -0
  173. package/src/posture/accuracy-scorecard.js +98 -9
  174. package/src/posture/artifact-registry.js +5 -0
  175. package/src/posture/assurance/evidence-registry.js +215 -0
  176. package/src/posture/assurance/release-package-verify.js +135 -0
  177. package/src/posture/assurance/release-package.js +118 -0
  178. package/src/posture/assurance/release-verdict.js +94 -0
  179. package/src/posture/assurance/waiver.js +200 -0
  180. package/src/posture/compliance-truth.js +100 -0
  181. package/src/posture/evaluation/scan-child.js +3 -1
  182. package/src/posture/evaluation/why-missed.js +3 -1
  183. package/src/posture/exploitability-evidence.js +141 -0
  184. package/src/posture/fix-verify.js +4 -2
  185. package/src/posture/fleet/exposure-ranking.js +115 -0
  186. package/src/posture/fleet/service-chain-graph.js +150 -0
  187. package/src/posture/graph-reconciliation.js +154 -0
  188. package/src/posture/provenance/coverage.js +103 -0
  189. package/src/posture/provenance/git-evidence.js +84 -0
  190. package/src/posture/provenance/origin-resolver.js +7 -1
  191. package/src/posture/provenance/predicate-replay.js +14 -4
  192. package/src/posture/runtime-correlation.js +61 -15
  193. package/src/posture/runtime-explanation.js +116 -0
  194. package/src/posture/runtime-trace-ingest.js +194 -0
  195. package/src/posture/scan-checkpoint.js +38 -10
  196. package/src/posture/waf-ingest.js +7 -2
  197. package/src/report/index.js +4 -0
  198. package/src/report/oscal.js +38 -0
  199. package/src/report/perspectives.js +150 -0
  200. package/src/sast/_comment-strip.js +8 -1
  201. package/src/sast/ruby.js +26 -0
  202. package/src/util/string-memo.js +38 -0
@@ -2,245 +2,6 @@ export const id = 4142;
2
2
  export const ids = [4142];
3
3
  export const modules = {
4
4
 
5
- /***/ 25517:
6
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
7
-
8
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9
- /* harmony export */ $: () => (/* binding */ ORACLE_TYPES),
10
- /* harmony export */ U: () => (/* binding */ evaluateOracle)
11
- /* harmony export */ });
12
- // Deterministic security oracles. A model may SELECT an oracle and propose its parameters; it may never decide that the
13
- // oracle succeeded. Each oracle is a pure function of an Observation gathered by the TRUSTED runner (never by the model):
14
- //
15
- // Observation = {
16
- // exitCode, signal, timedOut, stdout, stderr,
17
- // canaries: { <name>: { exists, digestBefore, digestAfter } } // checked by the runner on disk, after the run
18
- // callbacks: [{ nonce }] // hits recorded by the runner's loopback listener
19
- // nonce // per-run random token the target cannot predict
20
- // }
21
- //
22
- // An oracle returns { fired, reason }. `fired:false` with `inconclusive:true` means the observation could not decide
23
- // (for example a timeout); it is never treated as "not exploitable".
24
- const ORACLE_TYPES = Object.freeze([
25
- 'crash_sanitizer', 'command_execution', 'unauthorized_http_access', 'unauthorized_db_read', 'database_mutation',
26
- 'filesystem_mutation', 'outbound_callback', 'authentication_bypass', 'arbitrary_assertion',
27
- ]);
28
-
29
- const SANITIZER_RE = /(AddressSanitizer|UndefinedBehaviorSanitizer|stack-buffer-overflow|heap-buffer-overflow|SEGV on unknown address|stack smashing detected|buffer overflow detected)/i;
30
- const CRASH_SIGNALS = new Set(['SIGSEGV', 'SIGABRT', 'SIGBUS', 'SIGILL', 'SIGFPE']);
31
-
32
- const out = (fired, reason, extra = {}) => ({ fired, reason, ...extra });
33
- const inconclusive = (reason) => ({ fired: false, inconclusive: true, reason });
34
- const has = (obs, text) => typeof text === 'string' && text.length > 0 && `${obs.stdout || ''}${obs.stderr || ''}`.includes(text);
35
-
36
- const IMPL = {
37
- crash_sanitizer(obs) {
38
- if (SANITIZER_RE.test(obs.stderr || '')) return out(true, 'sanitizer or runtime memory-safety report on stderr');
39
- if (obs.signal && CRASH_SIGNALS.has(obs.signal)) return out(true, `process terminated by ${obs.signal}`);
40
- if (obs.timedOut) return inconclusive('run timed out before a crash could be judged');
41
- return out(false, 'no crash signal and no sanitizer report');
42
- },
43
- // The injected payload asks the shell/interpreter to create a file named after the per-run nonce inside the
44
- // watched canary directory. The target cannot create it unless attacker data reached a command.
45
- command_execution(obs, p) {
46
- const c = obs.canaries?.[p.canary || 'command'];
47
- if (!c) return inconclusive('command canary was not armed by the runner');
48
- if (c.exists && !c.existedBefore) return out(true, 'nonce-named canary file created by an injected command');
49
- if (obs.timedOut) return inconclusive('run timed out before the canary could be judged');
50
- return out(false, 'canary file not created');
51
- },
52
- // A secret planted behind authorization (never shown to the exploit client). Seeing the nonce-bearing secret in the
53
- // client's output while the actor held no credential is the violation.
54
- unauthorized_http_access(obs, p) {
55
- const secret = obs.secrets?.[p.secret || 'http'];
56
- if (!secret) return inconclusive('protected secret was not armed by the runner');
57
- if (has(obs, secret)) return out(true, 'protected resource content returned to an unauthenticated actor');
58
- if (obs.timedOut) return inconclusive('run timed out');
59
- return out(false, 'protected content not observed');
60
- },
61
- unauthorized_db_read(obs, p) {
62
- const secret = obs.secrets?.[p.secret || 'db'];
63
- if (!secret) return inconclusive('database canary row was not armed by the runner');
64
- if (has(obs, secret)) return out(true, 'row the actor may not read was returned');
65
- if (obs.timedOut) return inconclusive('run timed out');
66
- return out(false, 'canary row value not observed');
67
- },
68
- database_mutation(obs, p) {
69
- const c = obs.canaries?.[p.canary || 'db'];
70
- if (!c) return inconclusive('database canary was not armed by the runner');
71
- if (c.digestBefore && c.digestAfter && c.digestBefore !== c.digestAfter) return out(true, 'protected database state changed');
72
- if (obs.timedOut) return inconclusive('run timed out');
73
- return out(false, 'protected database state unchanged');
74
- },
75
- filesystem_mutation(obs, p) {
76
- const c = obs.canaries?.[p.canary || 'fs'];
77
- if (!c) return inconclusive('filesystem canary was not armed by the runner');
78
- if ((c.exists && !c.existedBefore) || (c.digestBefore && c.digestAfter && c.digestBefore !== c.digestAfter)) return out(true, 'file outside the permitted area was created or modified');
79
- if (obs.timedOut) return inconclusive('run timed out');
80
- return out(false, 'protected path unchanged');
81
- },
82
- outbound_callback(obs) {
83
- if (obs.callbackUnavailable) return { fired: false, unsupported: true, reason: 'loopback callback listener is not available on this backend' };
84
- const hit = (obs.callbacks || []).some((c) => c && c.nonce && c.nonce === obs.nonce);
85
- if (hit) return out(true, 'nonce-bearing request reached the runner-controlled listener');
86
- if (obs.timedOut) return inconclusive('run timed out');
87
- return out(false, 'no nonce-bearing callback received');
88
- },
89
- authentication_bypass(obs, p) {
90
- const secret = obs.secrets?.[p.secret || 'auth'];
91
- if (!secret) return inconclusive('protected secret was not armed by the runner');
92
- if (has(obs, secret)) return out(true, 'privileged content returned without valid credentials');
93
- if (obs.timedOut) return inconclusive('run timed out');
94
- return out(false, 'privileged content not observed without credentials');
95
- },
96
- // Declarative only: no code, no regex supplied by a model. Operators are a closed set.
97
- arbitrary_assertion(obs, p) {
98
- const a = p.assert;
99
- if (!a || typeof a !== 'object') return inconclusive('assertion missing');
100
- if (obs.timedOut) return inconclusive('run timed out');
101
- if ('exitCode' in a) return a.exitCode === obs.exitCode ? out(true, `exit code was ${obs.exitCode}`) : out(false, `exit code was ${obs.exitCode}`);
102
- if ('stdoutIncludes' in a) return has({ stdout: obs.stdout }, String(a.stdoutIncludes)) ? out(true, 'stdout contained the asserted text') : out(false, 'stdout did not contain the asserted text');
103
- if ('stderrIncludes' in a) return has({ stderr: obs.stderr }, String(a.stderrIncludes)) ? out(true, 'stderr contained the asserted text') : out(false, 'stderr did not contain the asserted text');
104
- return inconclusive('unsupported assertion operator');
105
- },
106
- };
107
-
108
- function evaluateOracle(spec, observation) {
109
- if (!spec || !ORACLE_TYPES.includes(spec.type)) return { fired: false, unsupported: true, reason: `unknown oracle type: ${String(spec?.type)}` };
110
- if (!observation || typeof observation !== 'object') return inconclusive('no observation');
111
- try { return IMPL[spec.type](observation, spec.params || {}); } catch (e) { return inconclusive(`oracle error: ${e.message}`); }
112
- }
113
-
114
-
115
- /***/ }),
116
-
117
- /***/ 37055:
118
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
119
-
120
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
121
- /* harmony export */ IW: () => (/* binding */ verifierView),
122
- /* harmony export */ V2: () => (/* binding */ substitute),
123
- /* harmony export */ Yj: () => (/* binding */ LANGUAGES),
124
- /* harmony export */ dw: () => (/* binding */ canonicalize),
125
- /* harmony export */ mC: () => (/* binding */ validateReproducer),
126
- /* harmony export */ sc: () => (/* binding */ sha256),
127
- /* harmony export */ we: () => (/* binding */ reproducerDigest)
128
- /* harmony export */ });
129
- /* unused harmony exports MAX_FILES, MAX_FILE_BYTES, isSafeRelPath */
130
- /* harmony import */ var node_crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(77598);
131
- /* harmony import */ var _oracles_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(25517);
132
- // Serialized reproducer: the ONLY thing an independent verifier receives (besides revision, finding id and oracle).
133
- // It carries no reasoning, no model output and no prior results. Everything per-run (nonce, secrets, canary paths,
134
- // callback URL) is a placeholder substituted fresh by the trusted runner, so a replay can never reuse a stale value
135
- // and a target cannot learn the values in advance.
136
-
137
-
138
-
139
- const REPRODUCER_SCHEMA = 'agentic-security/reproducer';
140
- const REPRODUCER_VERSION = 1;
141
- const LANGUAGES = Object.freeze(['javascript', 'typescript', 'python', 'java', 'c', 'cpp', 'csharp']);
142
- const MAX_FILES = 64;
143
- const MAX_FILE_BYTES = 256 * 1024;
144
- const MAX_TOTAL_BYTES = 1024 * 1024;
145
- const PLACEHOLDER_RE = /\{\{([A-Z_]+)(?::([a-z0-9_-]{1,32}))?\}\}/g;
146
- const ALLOWED_PLACEHOLDERS = new Set(['NONCE', 'SECRET', 'CANARY', 'CALLBACK_URL', 'CALLBACK_PORT', 'ROOT', 'NODE', 'PYTHON', 'JAVA', 'JAVAC', 'CC']);
147
-
148
- function isSafeRelPath(rel) {
149
- if (typeof rel !== 'string' || !rel || rel.length > 200) return false;
150
- if (rel.startsWith('/') || rel.includes('\0') || rel.includes('\\')) return false;
151
- if (['canary', 'tmp'].includes(rel.split('/')[0])) return false;
152
- return rel.split('/').every((seg) => seg && seg !== '.' && seg !== '..' && !seg.startsWith('__oracle_'));
153
- }
154
-
155
- /** Canonical JSON (sorted keys) so identical reproducers hash identically regardless of key order. */
156
- function canonicalize(v) {
157
- if (Array.isArray(v)) return `[${v.map(canonicalize).join(',')}]`;
158
- if (v && typeof v === 'object') return `{${Object.keys(v).sort().map((k) => `${JSON.stringify(k)}:${canonicalize(v[k])}`).join(',')}}`;
159
- return JSON.stringify(v);
160
- }
161
- const sha256 = (s) => (0,node_crypto__WEBPACK_IMPORTED_MODULE_0__.createHash)('sha256').update(s).digest('hex');
162
- const reproducerDigest = (r) => sha256(canonicalize(r));
163
-
164
- function validateReproducer(r) {
165
- const errs = [];
166
- if (!r || typeof r !== 'object' || Array.isArray(r)) return ['reproducer must be an object'];
167
- if (r.schema !== REPRODUCER_SCHEMA) errs.push('unknown schema');
168
- if (r.version !== REPRODUCER_VERSION) errs.push('unsupported reproducer version');
169
- if (typeof r.findingId !== 'string' || !r.findingId || r.findingId.length > 200) errs.push('findingId required');
170
- if (!LANGUAGES.includes(r.lang)) errs.push(`unsupported language: ${String(r.lang)}`);
171
- if (!r.oracle || !_oracles_js__WEBPACK_IMPORTED_MODULE_1__/* .ORACLE_TYPES */ .$.includes(r.oracle.type)) errs.push(`unknown oracle: ${String(r.oracle?.type)}`);
172
- const files = r.files ?? {};
173
- if (typeof files !== 'object' || Array.isArray(files)) errs.push('files must be an object');
174
- else {
175
- const names = Object.keys(files);
176
- if (names.length > MAX_FILES) errs.push(`file count must be at most ${MAX_FILES}`);
177
- let total = 0;
178
- for (const n of names) {
179
- if (!isSafeRelPath(n)) { errs.push(`unsafe file path: ${n}`); continue; }
180
- if (typeof files[n] !== 'string') { errs.push(`file ${n} must be a string`); continue; }
181
- const b = Buffer.byteLength(files[n]);
182
- total += b;
183
- if (b > MAX_FILE_BYTES) errs.push(`file ${n} exceeds ${MAX_FILE_BYTES} bytes`);
184
- }
185
- if (total > MAX_TOTAL_BYTES) errs.push('reproducer exceeds total size limit');
186
- }
187
- const sourceNames = r.sources && typeof r.sources === 'object' && !Array.isArray(r.sources) ? Object.keys(r.sources) : [];
188
- if (Object.keys(files).length + sourceNames.length === 0) errs.push('reproducer must declare at least one file or source');
189
- for (const key of ['build', 'run']) {
190
- const a = r[key];
191
- if (a == null && key === 'build') continue;
192
- if (!Array.isArray(a) || !a.length || !a.every((x) => typeof x === 'string' && x.length < 2000 && !x.includes('\0'))) errs.push(`${key} must be a non-empty argv array of strings (no shell string)`);
193
- }
194
- for (const text of [...Object.values(files || {}), ...(r.build || []), ...(r.run || [])]) {
195
- if (typeof text !== 'string') continue;
196
- for (const m of text.matchAll(PLACEHOLDER_RE)) if (!ALLOWED_PLACEHOLDERS.has(m[1])) errs.push(`unknown placeholder {{${m[1]}}}`);
197
- }
198
- if (r.watch != null) {
199
- if (typeof r.watch !== 'object' || Array.isArray(r.watch)) errs.push('watch must be an object');
200
- else for (const [k, v] of Object.entries(r.watch)) if (!/^[a-z0-9_-]{1,32}$/.test(k) || !isSafeRelPath(v)) errs.push(`bad watch entry: ${k}`);
201
- }
202
- if (r.env != null) {
203
- if (typeof r.env !== 'object' || Array.isArray(r.env)) errs.push('env must be an object');
204
- else for (const [k, v] of Object.entries(r.env)) {
205
- if (!/^[A-Z][A-Z0-9_]{0,63}$/.test(k)) errs.push(`bad env var name: ${k}`);
206
- if (typeof v !== 'string' || v.length > 4096) errs.push(`env value for ${k} must be a short string`);
207
- }
208
- }
209
- if (r.sources != null) {
210
- if (typeof r.sources !== 'object' || Array.isArray(r.sources)) errs.push('sources must be an object');
211
- else for (const [dest, src] of Object.entries(r.sources)) if (!isSafeRelPath(dest) || !isSafeRelPath(src)) errs.push(`bad sources entry: ${dest}`);
212
- }
213
- if (r.network != null && !['none', 'callback'].includes(r.network)) errs.push('network must be none or callback');
214
- return errs;
215
- }
216
-
217
- /** The view handed to an independent verifier: exactly the reproducer, plus identifiers. Nothing else. */
218
- function verifierView({ revision, reproducer, findingId, oracle }) {
219
- return Object.freeze({ revision: revision ?? null, findingId, oracle, reproducer: structuredClone(reproducer) });
220
- }
221
-
222
- function substitute(text, ctx) {
223
- return text.replace(PLACEHOLDER_RE, (whole, name, arg) => {
224
- switch (name) {
225
- case 'NONCE': return ctx.nonce;
226
- case 'SECRET': return ctx.secret(arg || 'default');
227
- case 'CANARY': return ctx.canary(arg || 'default');
228
- case 'CALLBACK_URL': return ctx.callbackUrl ?? whole;
229
- case 'CALLBACK_PORT': return String(ctx.callbackPort ?? '');
230
- case 'ROOT': return ctx.root;
231
- case 'NODE': return ctx.tools.node;
232
- case 'PYTHON': return ctx.tools.python ?? whole;
233
- case 'JAVA': return ctx.tools.java ?? whole;
234
- case 'JAVAC': return ctx.tools.javac ?? whole;
235
- case 'CC': return ctx.tools.cc ?? whole;
236
- default: return whole;
237
- }
238
- });
239
- }
240
-
241
-
242
- /***/ }),
243
-
244
5
  /***/ 12090:
245
6
  /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
246
7