circle-ir 3.68.0 → 3.70.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.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Pass: cache-no-vary (CWE-524, category: security)
3
+ *
4
+ * Pattern pass — flags HTTP handlers that set a *shared-cacheable*
5
+ * `Cache-Control` directive (`public` or implicit-public + positive `max-age`)
6
+ * **AND** read authenticated or user-scoped state (cookies / Authorization
7
+ * header / session), **AND** do not set `Vary: Cookie` / `Vary: Authorization`.
8
+ *
9
+ * In that configuration a shared cache (CDN, reverse proxy, ISP cache) keys
10
+ * the response by URL only and is free to serve user A's body to user B —
11
+ * the canonical CWE-524 leak.
12
+ *
13
+ * Languages: JavaScript / TypeScript (Express-style `res.setHeader` etc.),
14
+ * Python (Flask / Django / FastAPI), Go (`net/http`, gin), Java (Servlet /
15
+ * Spring).
16
+ *
17
+ * Trigger mode: strict + auth-qualifier. Skips:
18
+ * - `Cache-Control: private` / `no-store` / `no-cache`
19
+ * - `max-age=0` (effectively non-cacheable)
20
+ * - Handlers with no auth/session/cookie read
21
+ * - Handlers that set `Vary: Cookie|Authorization|*`
22
+ * - Test files (`*.test.*`, `*.spec.*`, `__tests__/`, `tests/`)
23
+ *
24
+ * Closes: cognium-dev #96 L91.
25
+ */
26
+ import type { AnalysisPass, PassContext } from '../../graph/analysis-pass.js';
27
+ export interface CacheNoVaryResult {
28
+ findings: Array<{
29
+ line: number;
30
+ language: string;
31
+ handler: string | null;
32
+ cacheValue: string;
33
+ }>;
34
+ }
35
+ export declare class CacheNoVaryPass implements AnalysisPass<CacheNoVaryResult> {
36
+ readonly name = "cache-no-vary";
37
+ readonly category: "security";
38
+ run(ctx: PassContext): CacheNoVaryResult;
39
+ }
40
+ //# sourceMappingURL=cache-no-vary-pass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-no-vary-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/cache-no-vary-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAmD9E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;CACJ;AA2ND,qBAAa,eAAgB,YAAW,YAAY,CAAC,iBAAiB,CAAC;IACrE,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,iBAAiB;CAkHzC"}
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Pass: cache-no-vary (CWE-524, category: security)
3
+ *
4
+ * Pattern pass — flags HTTP handlers that set a *shared-cacheable*
5
+ * `Cache-Control` directive (`public` or implicit-public + positive `max-age`)
6
+ * **AND** read authenticated or user-scoped state (cookies / Authorization
7
+ * header / session), **AND** do not set `Vary: Cookie` / `Vary: Authorization`.
8
+ *
9
+ * In that configuration a shared cache (CDN, reverse proxy, ISP cache) keys
10
+ * the response by URL only and is free to serve user A's body to user B —
11
+ * the canonical CWE-524 leak.
12
+ *
13
+ * Languages: JavaScript / TypeScript (Express-style `res.setHeader` etc.),
14
+ * Python (Flask / Django / FastAPI), Go (`net/http`, gin), Java (Servlet /
15
+ * Spring).
16
+ *
17
+ * Trigger mode: strict + auth-qualifier. Skips:
18
+ * - `Cache-Control: private` / `no-store` / `no-cache`
19
+ * - `max-age=0` (effectively non-cacheable)
20
+ * - Handlers with no auth/session/cookie read
21
+ * - Handlers that set `Vary: Cookie|Authorization|*`
22
+ * - Test files (`*.test.*`, `*.spec.*`, `__tests__/`, `tests/`)
23
+ *
24
+ * Closes: cognium-dev #96 L91.
25
+ */
26
+ // Header value parsing -------------------------------------------------------
27
+ function isSharedCacheable(value) {
28
+ const v = value.toLowerCase();
29
+ if (/\b(private|no-store|no-cache)\b/.test(v))
30
+ return false;
31
+ const pub = /\bpublic\b/.test(v);
32
+ const maxMatch = /\b(?:s-maxage|max-age)\s*=\s*(\d+)/.exec(v);
33
+ const positiveMax = maxMatch ? Number(maxMatch[1]) > 0 : false;
34
+ return pub || positiveMax;
35
+ }
36
+ function isVaryCovering(value) {
37
+ const v = value.toLowerCase();
38
+ return /\b(cookie|authorization|\*)\b/.test(v);
39
+ }
40
+ // Source-text auth-signal regexes (per-language) -----------------------------
41
+ const JS_AUTH_SIGNAL_RE = /\b(?:req|request)\s*\.\s*(?:cookies|session|user(?:Id|Name)?)\b|\b(?:req|request)\s*\.\s*headers\s*\.\s*(?:cookie|authorization)\b|\bres(?:ponse)?\s*\.\s*cookie\s*\(/i;
42
+ const PY_AUTH_SIGNAL_RE = /\brequest\s*\.\s*cookies\b|\brequest\s*\.\s*headers\s*\.\s*get\s*\(\s*['"]Authorization['"]|\brequest\s*\.\s*authorization\b|\bsession\s*\[|\b(?:g\.user|current_user)\b|\bset_cookie\s*\(/i;
43
+ const GO_AUTH_SIGNAL_RE = /\br\s*\.\s*Cookie\s*\(|\br\s*\.\s*Header\s*(?:\(\)|\.)\s*\.?\s*Get\s*\(\s*"(?:Cookie|Authorization)"|\br\s*\.\s*BasicAuth\s*\(|\bhttp\s*\.\s*SetCookie\s*\(|\bc\s*\.\s*(?:GetHeader|Cookie|SetCookie)\s*\(/;
44
+ const JAVA_AUTH_SIGNAL_RE = /@CookieValue\b|@RequestHeader\s*\(\s*"(?:Cookie|Authorization)"|\brequest\s*\.\s*getCookies\s*\(|\brequest\s*\.\s*getHeader\s*\(\s*"(?:Cookie|Authorization)"|\bresponse\s*\.\s*addCookie\s*\(|\bSecurityContextHolder\b|\bPrincipal\s+\w+|\bAuthentication\s+\w+/;
45
+ // Source-text cache/vary patterns (for shapes that are not extracted as IR
46
+ // calls — Python subscript assignments + decorators).
47
+ const PY_CACHE_HEADER_ASSIGN_RE = /\w+(?:\s*\.\s*\w+)*\s*\.\s*headers\s*\[\s*['"]Cache-Control['"]\s*\]\s*=\s*(['"])([^'"]*)\1/i;
48
+ const PY_VARY_HEADER_ASSIGN_RE = /\w+(?:\s*\.\s*\w+)*\s*\.\s*headers\s*\[\s*['"]Vary['"]\s*\]\s*=\s*(['"])([^'"]*)\1/i;
49
+ const PY_VARY_DECORATOR_RE = /^\s*@\s*(?:vary_on_cookie|vary_on_headers)\b/;
50
+ const PY_CACHE_CONTROL_DECORATOR_RE = /^\s*@\s*cache_control\s*\(([^)]*)\)/;
51
+ // Per-language header-setting method tables ----------------------------------
52
+ const JS_HEADER_METHODS = new Set(['setHeader', 'set', 'header']);
53
+ const GO_HEADER_METHODS = new Set(['Set', 'Add']);
54
+ const JAVA_HEADER_METHODS = new Set(['setHeader', 'addHeader']);
55
+ // JS receivers we treat as response objects.
56
+ const JS_RES_RECEIVERS = new Set(['res', 'response', 'ctx']);
57
+ function classifyCall(call, language) {
58
+ const method = call.method_name;
59
+ const receiver = (call.receiver ?? '').trim();
60
+ const arg0 = call.arguments[0]?.literal ?? null;
61
+ const arg1 = call.arguments[1]?.literal ?? null;
62
+ if (language === 'javascript' || language === 'typescript') {
63
+ if (JS_RES_RECEIVERS.has(receiver) && JS_HEADER_METHODS.has(method)) {
64
+ const header = (arg0 ?? '').toLowerCase();
65
+ if (header === 'cache-control' && arg1 && isSharedCacheable(arg1)) {
66
+ return { kind: 'cache-public', value: arg1 };
67
+ }
68
+ if (header === 'vary' && arg1 && isVaryCovering(arg1)) {
69
+ return { kind: 'vary' };
70
+ }
71
+ }
72
+ if (JS_RES_RECEIVERS.has(receiver) && method === 'vary') {
73
+ const v = arg0 ?? '';
74
+ if (isVaryCovering(v) || v === '')
75
+ return { kind: 'vary' };
76
+ }
77
+ if (JS_RES_RECEIVERS.has(receiver) && method === 'cookie') {
78
+ // Set-Cookie — auth-bearing response.
79
+ return { kind: 'auth' };
80
+ }
81
+ return null;
82
+ }
83
+ if (language === 'python') {
84
+ // Auth signals via call.
85
+ if (receiver === 'request.cookies' || receiver === 'request.session') {
86
+ return { kind: 'auth' };
87
+ }
88
+ if (receiver === 'request.headers' && method === 'get') {
89
+ const v = (arg0 ?? '').toLowerCase();
90
+ if (v === 'authorization' || v === 'cookie')
91
+ return { kind: 'auth' };
92
+ }
93
+ if ((receiver === 'response' || receiver === 'resp') &&
94
+ method === 'set_cookie') {
95
+ return { kind: 'auth' };
96
+ }
97
+ // Vary / cache via call.
98
+ if (method === 'patch_vary_headers')
99
+ return { kind: 'vary' };
100
+ if (method === 'patch_cache_control') {
101
+ const argTxt = call.arguments.map((a) => a.expression ?? '').join(',');
102
+ if (/\bpublic\s*=\s*True\b/.test(argTxt)) {
103
+ return { kind: 'cache-public', value: argTxt };
104
+ }
105
+ }
106
+ return null;
107
+ }
108
+ if (language === 'go') {
109
+ // Cache / Vary header via w.Header().Set/Add or c.Header (gin).
110
+ if ((receiver === 'w.Header()' || receiver === 'rw.Header()') &&
111
+ GO_HEADER_METHODS.has(method)) {
112
+ const header = (arg0 ?? '').toLowerCase();
113
+ if (header === 'cache-control' && arg1 && isSharedCacheable(arg1)) {
114
+ return { kind: 'cache-public', value: arg1 };
115
+ }
116
+ if (header === 'vary' && arg1 && isVaryCovering(arg1)) {
117
+ return { kind: 'vary' };
118
+ }
119
+ }
120
+ if (receiver === 'c' && method === 'Header') {
121
+ const header = (arg0 ?? '').toLowerCase();
122
+ if (header === 'cache-control' && arg1 && isSharedCacheable(arg1)) {
123
+ return { kind: 'cache-public', value: arg1 };
124
+ }
125
+ if (header === 'vary' && arg1 && isVaryCovering(arg1)) {
126
+ return { kind: 'vary' };
127
+ }
128
+ }
129
+ // Auth signals.
130
+ if (receiver === 'r' && (method === 'Cookie' || method === 'BasicAuth')) {
131
+ return { kind: 'auth' };
132
+ }
133
+ if ((receiver === 'r.Header' || receiver === 'r.Header()') &&
134
+ method === 'Get') {
135
+ const v = (arg0 ?? '').toLowerCase();
136
+ if (v === 'cookie' || v === 'authorization')
137
+ return { kind: 'auth' };
138
+ }
139
+ if (receiver === 'http' && method === 'SetCookie')
140
+ return { kind: 'auth' };
141
+ if (receiver === 'c' &&
142
+ (method === 'Cookie' || method === 'GetHeader' || method === 'SetCookie')) {
143
+ return { kind: 'auth' };
144
+ }
145
+ return null;
146
+ }
147
+ if (language === 'java') {
148
+ if ((receiver === 'response' || receiver === 'resp') &&
149
+ JAVA_HEADER_METHODS.has(method)) {
150
+ const header = (arg0 ?? '').toLowerCase();
151
+ if (header === 'cache-control' && arg1 && isSharedCacheable(arg1)) {
152
+ return { kind: 'cache-public', value: arg1 };
153
+ }
154
+ if (header === 'vary' && arg1 && isVaryCovering(arg1)) {
155
+ return { kind: 'vary' };
156
+ }
157
+ }
158
+ if ((receiver === 'headers' || receiver === 'httpHeaders') &&
159
+ method === 'setCacheControl') {
160
+ return { kind: 'cache-public', value: 'HttpHeaders.setCacheControl(...)' };
161
+ }
162
+ if ((receiver === 'headers' || receiver === 'httpHeaders') &&
163
+ method === 'setVary') {
164
+ return { kind: 'vary' };
165
+ }
166
+ // Auth signals.
167
+ if (receiver === 'request' && method === 'getCookies') {
168
+ return { kind: 'auth' };
169
+ }
170
+ if (receiver === 'request' && method === 'getHeader') {
171
+ const v = (arg0 ?? '').toLowerCase();
172
+ if (v === 'cookie' || v === 'authorization')
173
+ return { kind: 'auth' };
174
+ }
175
+ if ((receiver === 'response' || receiver === 'resp') &&
176
+ method === 'addCookie') {
177
+ return { kind: 'auth' };
178
+ }
179
+ return null;
180
+ }
181
+ return null;
182
+ }
183
+ function authSignalRegex(language) {
184
+ switch (language) {
185
+ case 'javascript':
186
+ case 'typescript':
187
+ return JS_AUTH_SIGNAL_RE;
188
+ case 'python':
189
+ return PY_AUTH_SIGNAL_RE;
190
+ case 'go':
191
+ return GO_AUTH_SIGNAL_RE;
192
+ case 'java':
193
+ return JAVA_AUTH_SIGNAL_RE;
194
+ default:
195
+ return null;
196
+ }
197
+ }
198
+ function scanWindow(code, language, startLine, endLine) {
199
+ const lines = code.split('\n');
200
+ const lo = Math.max(0, startLine - 1);
201
+ const hi = Math.min(lines.length, endLine);
202
+ const out = { vary: false, auth: false };
203
+ const authRe = authSignalRegex(language);
204
+ for (let i = lo; i < hi; i++) {
205
+ const ln = lines[i];
206
+ if (authRe && authRe.test(ln))
207
+ out.auth = true;
208
+ if (language === 'python') {
209
+ if (!out.cachePublic) {
210
+ const mc = PY_CACHE_HEADER_ASSIGN_RE.exec(ln);
211
+ if (mc && isSharedCacheable(mc[2])) {
212
+ out.cachePublic = { line: i + 1, value: mc[2] };
213
+ }
214
+ }
215
+ if (!out.cachePublic) {
216
+ const md = PY_CACHE_CONTROL_DECORATOR_RE.exec(ln);
217
+ if (md) {
218
+ const argTxt = md[1];
219
+ if (/\bpublic\s*=\s*True\b/.test(argTxt) &&
220
+ (/\bmax_age\s*=\s*[1-9]\d*\b/.test(argTxt) || !/max_age/.test(argTxt))) {
221
+ out.cachePublic = { line: i + 1, value: argTxt };
222
+ }
223
+ }
224
+ }
225
+ if (!out.vary) {
226
+ const mv = PY_VARY_HEADER_ASSIGN_RE.exec(ln);
227
+ if (mv && isVaryCovering(mv[2]))
228
+ out.vary = true;
229
+ if (PY_VARY_DECORATOR_RE.test(ln))
230
+ out.vary = true;
231
+ }
232
+ }
233
+ }
234
+ return out;
235
+ }
236
+ export class CacheNoVaryPass {
237
+ name = 'cache-no-vary';
238
+ category = 'security';
239
+ run(ctx) {
240
+ const { graph, language, code } = ctx;
241
+ const file = graph.ir.meta.file;
242
+ const findings = [];
243
+ const isSupported = language === 'javascript' ||
244
+ language === 'typescript' ||
245
+ language === 'python' ||
246
+ language === 'go' ||
247
+ language === 'java';
248
+ if (!isSupported)
249
+ return { findings };
250
+ // Skip test / spec files — low-FP guardrail.
251
+ if (/(?:\.test|\.spec)\.[jt]sx?$/i.test(file) ||
252
+ /__tests__\/|\/tests?\//i.test(file)) {
253
+ return { findings };
254
+ }
255
+ // Group calls by handler.
256
+ const callsByHandler = new Map();
257
+ for (const call of graph.ir.calls) {
258
+ const key = call.in_method ?? '<top>';
259
+ let arr = callsByHandler.get(key);
260
+ if (!arr) {
261
+ arr = [];
262
+ callsByHandler.set(key, arr);
263
+ }
264
+ arr.push(call);
265
+ }
266
+ const emit = (line, handler, cacheValue) => {
267
+ if (findings.some((f) => f.line === line && f.handler === handler))
268
+ return;
269
+ findings.push({ line, language, handler, cacheValue });
270
+ ctx.addFinding({
271
+ id: `${this.name}-${file}-${line}`,
272
+ pass: this.name,
273
+ category: this.category,
274
+ rule_id: this.name,
275
+ cwe: 'CWE-524',
276
+ severity: 'medium',
277
+ level: 'warning',
278
+ message: `Response sets a shared-cacheable Cache-Control ('${cacheValue}') in ` +
279
+ `a handler that reads authenticated or user-scoped state, but does ` +
280
+ `not set 'Vary: Cookie' or 'Vary: Authorization'. A shared cache ` +
281
+ `(CDN, reverse proxy, ISP cache) keys the response by URL only and ` +
282
+ `may serve one user's body to another. (CWE-524)`,
283
+ file,
284
+ line,
285
+ fix: `Either add 'Vary: Cookie' (or 'Vary: Authorization') so caches key ` +
286
+ `on the user identity, or change the directive to 'private' / ` +
287
+ `'no-store' so the response is never shared-cached.`,
288
+ evidence: {
289
+ language,
290
+ handler: handler ?? '<top>',
291
+ cacheValue,
292
+ },
293
+ });
294
+ };
295
+ for (const [handlerKey, calls] of callsByHandler) {
296
+ const handler = handlerKey === '<top>' ? null : handlerKey;
297
+ const cachePublicHits = [];
298
+ let varyFromCalls = false;
299
+ let authFromCalls = false;
300
+ for (const call of calls) {
301
+ const cls = classifyCall(call, language);
302
+ if (!cls)
303
+ continue;
304
+ if (cls.kind === 'cache-public') {
305
+ cachePublicHits.push({
306
+ line: call.location.line,
307
+ value: cls.value ?? '',
308
+ });
309
+ }
310
+ else if (cls.kind === 'vary') {
311
+ varyFromCalls = true;
312
+ }
313
+ else if (cls.kind === 'auth') {
314
+ authFromCalls = true;
315
+ }
316
+ }
317
+ // Compute a widened source-text window around this handler's calls.
318
+ let minLine = Infinity;
319
+ let maxLine = -Infinity;
320
+ for (const c of calls) {
321
+ if (c.location?.line) {
322
+ minLine = Math.min(minLine, c.location.line);
323
+ maxLine = Math.max(maxLine, c.location.line);
324
+ }
325
+ }
326
+ if (minLine === Infinity)
327
+ continue;
328
+ const winStart = Math.max(1, minLine - 5);
329
+ const winEnd = maxLine + 5;
330
+ const winScan = scanWindow(code, language, winStart, winEnd);
331
+ if (winScan.cachePublic)
332
+ cachePublicHits.push(winScan.cachePublic);
333
+ const vary = varyFromCalls || winScan.vary;
334
+ const auth = authFromCalls || winScan.auth;
335
+ if (cachePublicHits.length === 0)
336
+ continue;
337
+ if (vary)
338
+ continue;
339
+ if (!auth)
340
+ continue;
341
+ // Emit one finding per handler (use first cache-public location).
342
+ emit(cachePublicHits[0].line, handler, cachePublicHits[0].value);
343
+ }
344
+ return { findings };
345
+ }
346
+ }
347
+ //# sourceMappingURL=cache-no-vary-pass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-no-vary-pass.js","sourceRoot":"","sources":["../../../src/analysis/passes/cache-no-vary-pass.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Pass: module-side-effect (CWE-829, category: security)
3
+ *
4
+ * Pattern pass — flags dangerous side effects executed at **module load /
5
+ * install / build time**, where no taint flow is involved (the bad behavior
6
+ * is hard-coded by an attacker, not user-driven). This is the canonical
7
+ * delivery vector for supply-chain droppers: shai-hulud-style TruffleHog
8
+ * harvesters in npm `postinstall`, Python `__init__.py` credential POST,
9
+ * Go `init()` exfil, Rust `build.rs` exec.
10
+ *
11
+ * Detection per language:
12
+ * JavaScript / TypeScript:
13
+ * - module-level call (`in_method == null`) to a high-risk API:
14
+ * `child_process.{exec,spawn,execSync,spawnSync}`,
15
+ * `https.request`, `http.request`,
16
+ * `fetch` / `axios.*` whose args reference `process.env` or `os.homedir`.
17
+ * - `package.json` source-text scan (when `meta.file` ends with
18
+ * `package.json`): a `scripts.(pre|post)?install` value that invokes a
19
+ * shell (`curl`, `wget`, `node -e`, `sh -c`, `eval`). Benign install
20
+ * scripts (`node-gyp rebuild`, `prebuild-install`, `husky install`,
21
+ * `patch-package`) are allowlisted.
22
+ *
23
+ * Python:
24
+ * - module-level call (`in_method == null`) to a high-risk API:
25
+ * `requests.{post,put}`, `urllib.request.urlopen`,
26
+ * `socket.{connect,create_connection}`, `subprocess.run`, `os.system`.
27
+ * - The call must reference an "env / secret" signal in any argument
28
+ * expression: `os.environ`, `pwd.getpw`, `glob.glob('/.../id_rsa`,
29
+ * `~/.ssh`, `/etc/passwd`, `home`, `pathlib.Path.home`. This keeps the
30
+ * FP rate near zero on benign module-level network setup.
31
+ *
32
+ * Go:
33
+ * - call inside a function named `init` (`in_method === 'init'`) whose
34
+ * callee is `exec.Command`, `http.Post`, `http.Get`, `net.LookupTXT`,
35
+ * `os.Setenv`.
36
+ *
37
+ * Rust:
38
+ * - file is a build script (`meta.file` ends with `build.rs`) AND callee
39
+ * is `Command::new` / `std::process::Command::new` / `reqwest::*`.
40
+ * `println!("cargo:...")` directives are the only intended `build.rs`
41
+ * side effect — those produce no IR call.
42
+ *
43
+ * Closes: cognium-dev #93 (npm postinstall dropper), #96 L47 (Python import-
44
+ * time harvest), #98 (Go init() + Rust build.rs install-time harvest).
45
+ */
46
+ import type { AnalysisPass, PassContext } from '../../graph/analysis-pass.js';
47
+ export interface ModuleSideEffectResult {
48
+ findings: Array<{
49
+ line: number;
50
+ language: string;
51
+ pattern: string;
52
+ api: string;
53
+ }>;
54
+ }
55
+ export declare class ModuleSideEffectPass implements AnalysisPass<ModuleSideEffectResult> {
56
+ readonly name = "module-side-effect";
57
+ readonly category: "security";
58
+ run(ctx: PassContext): ModuleSideEffectResult;
59
+ private detectCall;
60
+ /**
61
+ * Scan a package.json file for dangerous install-lifecycle scripts.
62
+ * Best-effort regex extraction — package.json is not a JS source per se but
63
+ * the analyzer routes it through the JS pipeline.
64
+ */
65
+ private scanPackageJson;
66
+ private fixFor;
67
+ }
68
+ //# sourceMappingURL=module-side-effect-pass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-side-effect-pass.d.ts","sourceRoot":"","sources":["../../../src/analysis/passes/module-side-effect-pass.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAuE9E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC,CAAC;CACJ;AAED,qBAAa,oBAAqB,YAAW,YAAY,CAAC,sBAAsB,CAAC;IAC/E,QAAQ,CAAC,IAAI,wBAAwB;IACrC,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,sBAAsB;IA2D7C,OAAO,CAAC,UAAU;IAiGlB;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,MAAM;CAwCf"}