circle-ir 3.141.0 → 3.144.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/configs/sink-semantics.json +53 -0
  2. package/dist/analysis/config-loader.d.ts +24 -2
  3. package/dist/analysis/config-loader.d.ts.map +1 -1
  4. package/dist/analysis/config-loader.js +92 -2
  5. package/dist/analysis/config-loader.js.map +1 -1
  6. package/dist/analysis/findings.d.ts +32 -0
  7. package/dist/analysis/findings.d.ts.map +1 -1
  8. package/dist/analysis/findings.js +52 -2
  9. package/dist/analysis/findings.js.map +1 -1
  10. package/dist/analysis/passes/language-sources-pass.d.ts +19 -0
  11. package/dist/analysis/passes/language-sources-pass.d.ts.map +1 -1
  12. package/dist/analysis/passes/language-sources-pass.js +133 -3
  13. package/dist/analysis/passes/language-sources-pass.js.map +1 -1
  14. package/dist/analysis/passes/scan-secrets-pass.d.ts.map +1 -1
  15. package/dist/analysis/passes/scan-secrets-pass.js +37 -4
  16. package/dist/analysis/passes/scan-secrets-pass.js.map +1 -1
  17. package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
  18. package/dist/analysis/passes/sink-filter-pass.js +10 -1
  19. package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
  20. package/dist/analysis/passes/sink-semantics-pass.d.ts +52 -0
  21. package/dist/analysis/passes/sink-semantics-pass.d.ts.map +1 -0
  22. package/dist/analysis/passes/sink-semantics-pass.js +100 -0
  23. package/dist/analysis/passes/sink-semantics-pass.js.map +1 -0
  24. package/dist/analysis/passes/source-semantics-pass.d.ts +66 -0
  25. package/dist/analysis/passes/source-semantics-pass.d.ts.map +1 -0
  26. package/dist/analysis/passes/source-semantics-pass.js +165 -0
  27. package/dist/analysis/passes/source-semantics-pass.js.map +1 -0
  28. package/dist/analysis/passes/taint-propagation-pass.js +91 -10
  29. package/dist/analysis/passes/taint-propagation-pass.js.map +1 -1
  30. package/dist/analysis/taint-matcher.d.ts.map +1 -1
  31. package/dist/analysis/taint-matcher.js +55 -3
  32. package/dist/analysis/taint-matcher.js.map +1 -1
  33. package/dist/analyzer.d.ts.map +1 -1
  34. package/dist/analyzer.js +14 -0
  35. package/dist/analyzer.js.map +1 -1
  36. package/dist/browser/circle-ir.js +363 -15
  37. package/dist/core/circle-ir-core.cjs +112 -8
  38. package/dist/core/circle-ir-core.js +112 -8
  39. package/dist/core/extractors/calls.js +14 -0
  40. package/dist/core/extractors/calls.js.map +1 -1
  41. package/dist/types/config.d.ts +47 -0
  42. package/dist/types/config.d.ts.map +1 -1
  43. package/dist/types/index.d.ts +43 -0
  44. package/dist/types/index.d.ts.map +1 -1
  45. package/package.json +1 -1
@@ -0,0 +1,53 @@
1
+ {
2
+ "$description": "Sink-semantics registry — cognium-dev #139 Tier A. Each entry maps a <ClassName>#<methodName> signature to the sink's real behavior class and the list of SinkType labels that must be dropped when that signature is emitted with that label. Consumed by SinkSemanticsPass (canonical #109). Simple-name class match; fully-qualified receiver types are reduced to the tail segment. Missing sink.class (unresolved receiver) falls through — the gate is false-negative-safe.",
3
+ "sinks": [
4
+ {
5
+ "signature": "Jedis#executeCommand",
6
+ "real_class": "db_protocol",
7
+ "overrides": ["command_injection", "code_injection"],
8
+ "note": "Redis wire-protocol serialization, not OS exec"
9
+ },
10
+ {
11
+ "signature": "Connection#executeCommand",
12
+ "real_class": "db_protocol",
13
+ "overrides": ["command_injection", "code_injection"],
14
+ "note": "Jedis abstract Connection base — same shape as Jedis.executeCommand"
15
+ },
16
+ {
17
+ "signature": "JedisCluster#executeCommand",
18
+ "real_class": "db_protocol",
19
+ "overrides": ["command_injection", "code_injection"],
20
+ "note": "Jedis cluster client — same shape as Jedis.executeCommand"
21
+ },
22
+ {
23
+ "signature": "Func1#exec",
24
+ "real_class": "functional_dispatch",
25
+ "overrides": ["command_injection", "code_injection"],
26
+ "note": "RxJava functional dispatch, not OS exec"
27
+ },
28
+ {
29
+ "signature": "Action0#call",
30
+ "real_class": "functional_dispatch",
31
+ "overrides": ["command_injection"],
32
+ "note": "RxJava Action0 dispatch"
33
+ },
34
+ {
35
+ "signature": "Action1#call",
36
+ "real_class": "functional_dispatch",
37
+ "overrides": ["command_injection"],
38
+ "note": "RxJava Action1 dispatch"
39
+ },
40
+ {
41
+ "signature": "Unsafe#defineAnonymousClass",
42
+ "real_class": "jdk_internal",
43
+ "overrides": ["code_injection"],
44
+ "note": "sun.misc.Unsafe JDK-internal reflective bridge — not attacker-controllable input"
45
+ },
46
+ {
47
+ "signature": "MethodHandle#invokeExact",
48
+ "real_class": "jdk_internal",
49
+ "overrides": ["code_injection"],
50
+ "note": "java.lang.invoke.MethodHandle — JDK-internal, not attacker-controllable"
51
+ }
52
+ ]
53
+ }
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Loads YAML configs from configs/sources/ and configs/sinks/
5
5
  */
6
- import type { SourceConfig, SinkConfig, TaintConfig, SourcePattern, SinkPattern, SanitizerPattern, HeaderRule } from '../types/config.js';
6
+ import type { SourceConfig, SinkConfig, SinkSemanticsConfig, SinkSemanticsEntry, TaintConfig, SourcePattern, SinkPattern, SanitizerPattern, HeaderRule } from '../types/config.js';
7
7
  /**
8
8
  * Parse YAML/JSON configuration content.
9
9
  * Uses JSON since the config files are actually JSON despite .yaml extension.
@@ -20,10 +20,21 @@ export declare function loadSinkConfigs(configs: SinkConfig[]): {
20
20
  sinks: SinkPattern[];
21
21
  sanitizers: SanitizerPattern[];
22
22
  };
23
+ /**
24
+ * Load and merge sink-semantics registry entries from one or more
25
+ * configs. Used by `SinkSemanticsPass` (cognium-dev #139 Tier A) to
26
+ * drop sinks whose emitted `SinkType` label disagrees with the
27
+ * registry's real-behavior classification.
28
+ */
29
+ export declare function loadSinkSemanticsConfigs(configs: SinkSemanticsConfig[]): SinkSemanticsEntry[];
23
30
  /**
24
31
  * Create a combined taint configuration from raw config contents.
32
+ *
33
+ * `sinkSemanticsContents` is optional to preserve backward
34
+ * compatibility with existing callers; passing an empty array (or
35
+ * omitting the argument) disables the sink-semantics gate.
25
36
  */
26
- export declare function createTaintConfig(sourceContents: string[], sinkContents: string[]): TaintConfig;
37
+ export declare function createTaintConfig(sourceContents: string[], sinkContents: string[], sinkSemanticsContents?: string[]): TaintConfig;
27
38
  /**
28
39
  * Embedded default configurations (subset for standalone use).
29
40
  * Full configs should be loaded from files when available.
@@ -31,6 +42,17 @@ export declare function createTaintConfig(sourceContents: string[], sinkContents
31
42
  export declare const DEFAULT_SOURCES: SourcePattern[];
32
43
  export declare const DEFAULT_SINKS: SinkPattern[];
33
44
  export declare const DEFAULT_SANITIZERS: SanitizerPattern[];
45
+ /**
46
+ * Embedded default sink-semantics registry (cognium-dev #139 Tier A).
47
+ * Mirrors `configs/sink-semantics.json` so the default gate is active
48
+ * in browser/Node.js callers that never call `createTaintConfig`.
49
+ *
50
+ * Each entry maps a `<ClassName>#<methodName>` receiver signature to
51
+ * the `SinkType` labels that should be dropped when the taint-matcher
52
+ * emits that signature with a mismatched label. Class match is
53
+ * simple-name and case-sensitive against `TaintSink.class`.
54
+ */
55
+ export declare const DEFAULT_SINK_SEMANTICS: SinkSemanticsEntry[];
34
56
  /**
35
57
  * Get the default taint configuration.
36
58
  */
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,GACrB,WAAW,CAQb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EA2b1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EAskDtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EA6RhD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAM9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/analysis/config-loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,UAAU,EACX,MAAM,oBAAoB,CAAC;AAE5B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAEjD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAiB1E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IACtD,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAcA;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,mBAAmB,EAAE,GAC7B,kBAAkB,EAAE,CAQtB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,cAAc,EAAE,MAAM,EAAE,EACxB,YAAY,EAAE,MAAM,EAAE,EACtB,qBAAqB,GAAE,MAAM,EAAO,GACnC,WAAW,CAYb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EA2b1C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,EA8kDtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,EA6RhD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,EAAE,kBAAkB,EAiDtD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAO9C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,UAAU,EA8F5C,CAAC"}
@@ -45,15 +45,36 @@ export function loadSinkConfigs(configs) {
45
45
  }
46
46
  return { sinks, sanitizers };
47
47
  }
48
+ /**
49
+ * Load and merge sink-semantics registry entries from one or more
50
+ * configs. Used by `SinkSemanticsPass` (cognium-dev #139 Tier A) to
51
+ * drop sinks whose emitted `SinkType` label disagrees with the
52
+ * registry's real-behavior classification.
53
+ */
54
+ export function loadSinkSemanticsConfigs(configs) {
55
+ const entries = [];
56
+ for (const config of configs) {
57
+ if (config.sinks) {
58
+ entries.push(...config.sinks);
59
+ }
60
+ }
61
+ return entries;
62
+ }
48
63
  /**
49
64
  * Create a combined taint configuration from raw config contents.
65
+ *
66
+ * `sinkSemanticsContents` is optional to preserve backward
67
+ * compatibility with existing callers; passing an empty array (or
68
+ * omitting the argument) disables the sink-semantics gate.
50
69
  */
51
- export function createTaintConfig(sourceContents, sinkContents) {
70
+ export function createTaintConfig(sourceContents, sinkContents, sinkSemanticsContents = []) {
52
71
  const sourceConfigs = sourceContents.map((c) => parseConfig(c));
53
72
  const sinkConfigs = sinkContents.map((c) => parseConfig(c));
73
+ const sinkSemanticsConfigs = sinkSemanticsContents.map((c) => parseConfig(c));
54
74
  const sources = loadSourceConfigs(sourceConfigs);
55
75
  const { sinks, sanitizers } = loadSinkConfigs(sinkConfigs);
56
- return { sources, sinks, sanitizers };
76
+ const sinkSemantics = loadSinkSemanticsConfigs(sinkSemanticsConfigs);
77
+ return { sources, sinks, sanitizers, sinkSemantics };
57
78
  }
58
79
  /**
59
80
  * Embedded default configurations (subset for standalone use).
@@ -776,6 +797,14 @@ export const DEFAULT_SINKS = [
776
797
  // reflection remains a downstream concern of body-writing sinks.
777
798
  { method: 'setHeader', class: 'HttpServletResponse', type: 'crlf', cwe: 'CWE-113', severity: 'medium', arg_positions: [1] },
778
799
  { method: 'addHeader', class: 'HttpServletResponse', type: 'crlf', cwe: 'CWE-113', severity: 'medium', arg_positions: [1] },
800
+ // Cookie constructor + addCookie — HTTP response splitting via cookie
801
+ // name/value (CWE-113). Reflects the #189 Sprint 92 V02SetCookie fixture
802
+ // where `res.addCookie(new Cookie(name, req.getParameter("v")))` allows
803
+ // CRLF injection into the Set-Cookie header. Both the ctor arg[1] (value)
804
+ // and the addCookie arg[0] (Cookie handle) are flagged so intermediate-var
805
+ // and inline-ctor shapes both surface.
806
+ { method: 'Cookie', class: 'constructor', type: 'crlf', cwe: 'CWE-113', severity: 'medium', arg_positions: [0, 1] },
807
+ { method: 'addCookie', class: 'HttpServletResponse', type: 'crlf', cwe: 'CWE-113', severity: 'medium', arg_positions: [0] },
779
808
  // Note: `sendRedirect` is primarily classified as `ssrf` / open-redirect
780
809
  // (CWE-601) further down — see entry near line 1195. CRLF via Location
781
810
  // header is a secondary concern; keeping the canonical SSRF entry avoids
@@ -2200,6 +2229,66 @@ export const DEFAULT_SANITIZERS = [
2200
2229
  { method: 'UUID', class: 'uuid', removes: ['sql_injection', 'command_injection', 'path_traversal', 'code_injection'] },
2201
2230
  { method: 'Decimal', class: 'decimal', removes: ['sql_injection', 'command_injection', 'path_traversal', 'code_injection'] },
2202
2231
  ];
2232
+ /**
2233
+ * Embedded default sink-semantics registry (cognium-dev #139 Tier A).
2234
+ * Mirrors `configs/sink-semantics.json` so the default gate is active
2235
+ * in browser/Node.js callers that never call `createTaintConfig`.
2236
+ *
2237
+ * Each entry maps a `<ClassName>#<methodName>` receiver signature to
2238
+ * the `SinkType` labels that should be dropped when the taint-matcher
2239
+ * emits that signature with a mismatched label. Class match is
2240
+ * simple-name and case-sensitive against `TaintSink.class`.
2241
+ */
2242
+ export const DEFAULT_SINK_SEMANTICS = [
2243
+ {
2244
+ signature: 'Jedis#executeCommand',
2245
+ real_class: 'db_protocol',
2246
+ overrides: ['command_injection', 'code_injection'],
2247
+ note: 'Redis wire-protocol serialization, not OS exec',
2248
+ },
2249
+ {
2250
+ signature: 'Connection#executeCommand',
2251
+ real_class: 'db_protocol',
2252
+ overrides: ['command_injection', 'code_injection'],
2253
+ note: 'Jedis abstract Connection base',
2254
+ },
2255
+ {
2256
+ signature: 'JedisCluster#executeCommand',
2257
+ real_class: 'db_protocol',
2258
+ overrides: ['command_injection', 'code_injection'],
2259
+ note: 'Jedis cluster client',
2260
+ },
2261
+ {
2262
+ signature: 'Func1#exec',
2263
+ real_class: 'functional_dispatch',
2264
+ overrides: ['command_injection', 'code_injection'],
2265
+ note: 'RxJava functional dispatch, not OS exec',
2266
+ },
2267
+ {
2268
+ signature: 'Action0#call',
2269
+ real_class: 'functional_dispatch',
2270
+ overrides: ['command_injection'],
2271
+ note: 'RxJava Action0 dispatch',
2272
+ },
2273
+ {
2274
+ signature: 'Action1#call',
2275
+ real_class: 'functional_dispatch',
2276
+ overrides: ['command_injection'],
2277
+ note: 'RxJava Action1 dispatch',
2278
+ },
2279
+ {
2280
+ signature: 'Unsafe#defineAnonymousClass',
2281
+ real_class: 'jdk_internal',
2282
+ overrides: ['code_injection'],
2283
+ note: 'sun.misc.Unsafe JDK-internal reflective bridge',
2284
+ },
2285
+ {
2286
+ signature: 'MethodHandle#invokeExact',
2287
+ real_class: 'jdk_internal',
2288
+ overrides: ['code_injection'],
2289
+ note: 'java.lang.invoke.MethodHandle — JDK-internal',
2290
+ },
2291
+ ];
2203
2292
  /**
2204
2293
  * Get the default taint configuration.
2205
2294
  */
@@ -2208,6 +2297,7 @@ export function getDefaultConfig() {
2208
2297
  sources: DEFAULT_SOURCES,
2209
2298
  sinks: DEFAULT_SINKS,
2210
2299
  sanitizers: DEFAULT_SANITIZERS,
2300
+ sinkSemantics: DEFAULT_SINK_SEMANTICS,
2211
2301
  };
2212
2302
  }
2213
2303
  // ============================================================================