circle-ir 3.179.0 → 3.181.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.
@@ -11282,6 +11282,35 @@ var DEFAULT_SOURCES = [
11282
11282
  { method: "get", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
11283
11283
  { method: "hget", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
11284
11284
  { method: "mget", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
11285
+ // --- Serverless transport channels (cognium-dev #213 first slice) ---
11286
+ //
11287
+ // AWS Lambda / API Gateway invocation-event properties. The Lambda
11288
+ // handler signature `(event, context) => …` (JS/TS) or
11289
+ // `def handler(event, context)` (Python) receives an `event` object
11290
+ // whose properties carry the untrusted HTTP-request-shaped payload:
11291
+ //
11292
+ // event.body — request body (string)
11293
+ // event.queryStringParameters — `?a=b` params
11294
+ // event.multiValueQueryStringParameters — `?a=1&a=2` params
11295
+ // event.pathParameters — path template captures
11296
+ // event.headers — request headers
11297
+ // event.multiValueHeaders — repeated headers
11298
+ // event.requestContext — API Gateway request context
11299
+ //
11300
+ // Vercel Serverless Functions and Cloudflare Workers both use `req`
11301
+ // / `request` receivers that are already covered by the Express-
11302
+ // style patterns above (line ~398). This block specifically covers
11303
+ // the `event`-shaped API Gateway convention that those don't reach.
11304
+ { property: "body", object: "event", type: "http_body", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
11305
+ { property: "queryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
11306
+ { property: "multiValueQueryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
11307
+ { property: "pathParameters", object: "event", type: "http_path", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
11308
+ { property: "headers", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
11309
+ { property: "multiValueHeaders", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
11310
+ { property: "body", object: "event", type: "http_body", severity: "high", property_tainted: true, languages: ["python"] },
11311
+ { property: "queryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["python"] },
11312
+ { property: "pathParameters", object: "event", type: "http_path", severity: "high", property_tainted: true, languages: ["python"] },
11313
+ { property: "headers", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["python"] },
11285
11314
  // --- JWT claims (unverified decode — PyJWT / jose / jsonwebtoken / auth0 java-jwt / golang-jwt) ---
11286
11315
  // A JWT's payload is *always* attacker-authored. Even after verification
11287
11316
  // the *contents* of the claims (username, role, custom fields) are not
@@ -12277,6 +12306,20 @@ var DEFAULT_SINKS = [
12277
12306
  // Sandbox/script security
12278
12307
  { method: "onNewInstance", class: "SandboxInterceptor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
12279
12308
  // Java Log Injection (slf4j / logback / java.util.logging) — CWE-117
12309
+ //
12310
+ // Classification decision — cognium-dev #264: Logger receivers stay
12311
+ // as log_injection (CWE-117), NOT format_string (CWE-134). The real
12312
+ // vulnerability with tainted data flowing into Logger.log(fmt, ...)
12313
+ // is log-forgery via CRLF injection, not format-string exploitation.
12314
+ // A genuine format_string vulnerability requires the FORMAT STRING
12315
+ // itself to be attacker-controlled, which is virtually never the
12316
+ // case in Logger APIs (the format string is a literal at the call
12317
+ // site). Adding format_string sinks for these same receivers would
12318
+ // duplicate the existing log_injection findings on every call site
12319
+ // without adding real signal. The rare edge case where a caller
12320
+ // passes `taintedFmt` at arg[0] is still caught by these entries
12321
+ // (via arg_positions[0] on the SLF4J-family methods), classified as
12322
+ // log_injection.
12280
12323
  // Issue #44: log.info/warn/error/debug emit the message argument and any
12281
12324
  // {} format arguments to the log stream. Untrusted input forwarded into
12282
12325
  // these calls allows log forging (newline injection) and downstream log
@@ -25490,7 +25533,19 @@ var JS_TAINTED_PATTERNS = [
25490
25533
  { pattern: /\bdocument\.title\b/, type: "dom_input" },
25491
25534
  { pattern: /\bhistory\.state\b/, type: "dom_input" },
25492
25535
  { pattern: /\blocalStorage\.getItem\b/, type: "dom_input" },
25493
- { pattern: /\bsessionStorage\.getItem\b/, type: "dom_input" }
25536
+ { pattern: /\bsessionStorage\.getItem\b/, type: "dom_input" },
25537
+ // AWS Lambda / API Gateway event-shape sources (cognium-dev #213
25538
+ // transport-channel first slice). The `event` parameter of a
25539
+ // Lambda handler carries the untrusted HTTP payload; forward-taint
25540
+ // tracking through `const q = event.body; sink(q)` needs the
25541
+ // regex here in addition to the property patterns in
25542
+ // config-loader.ts:DEFAULT_SOURCES.
25543
+ { pattern: /\bevent\.body\b/, type: "http_body" },
25544
+ { pattern: /\bevent\.queryStringParameters\b/, type: "http_param" },
25545
+ { pattern: /\bevent\.multiValueQueryStringParameters\b/, type: "http_param" },
25546
+ { pattern: /\bevent\.pathParameters\b/, type: "http_path" },
25547
+ { pattern: /\bevent\.headers\b/, type: "http_header" },
25548
+ { pattern: /\bevent\.multiValueHeaders\b/, type: "http_header" }
25494
25549
  ];
25495
25550
  var PYTHON_TAINTED_PATTERNS2 = [
25496
25551
  { pattern: /\brequest\.args\b/, type: "http_param" },
@@ -30008,7 +30063,7 @@ function findPythonTaintedFormatStringFindings(code, file) {
30008
30063
  }
30009
30064
  if (taintedVars.size === 0) return findings;
30010
30065
  const percentRe = /\b(\w+)\s*%\s*[\(\[\{"'\w]/;
30011
- const dotFormatRe = /\b(\w+)\s*\.\s*format\s*\(/;
30066
+ const dotFormatRe = /\b(\w+)\s*\.\s*(?:format|format_map)\s*\(/;
30012
30067
  const seen = /* @__PURE__ */ new Set();
30013
30068
  for (let i2 = 0; i2 < lines.length; i2++) {
30014
30069
  const line = lines[i2];
@@ -32892,6 +32947,12 @@ function resolveFastjsonFromGradle(buildGradle) {
32892
32947
  const version2 = direct[1];
32893
32948
  return { version: version2, noneAutotype: /_noneautotype/i.test(version2) };
32894
32949
  }
32950
+ const constraintsBlockRe = /['"(]\s*com\.alibaba:fastjson\s*['")]\s*\)?\s*\{[\s\S]*?\bversion\s*\{[\s\S]*?\b(?:strictly|require|prefer)\s+['"]([^'"\s]+)['"]/;
32951
+ const constraintsBlock = buildGradle.match(constraintsBlockRe);
32952
+ if (constraintsBlock) {
32953
+ const version2 = constraintsBlock[1];
32954
+ return { version: version2, noneAutotype: /_noneautotype/i.test(version2) };
32955
+ }
32895
32956
  const propRefRe = /['"(]\s*com\.alibaba:fastjson:\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?\s*['")]/;
32896
32957
  const propRef = buildGradle.match(propRefRe);
32897
32958
  if (!propRef) return null;
@@ -32904,6 +32965,51 @@ function resolveFastjsonFromGradle(buildGradle) {
32904
32965
  const version = def[1];
32905
32966
  return { version, noneAutotype: /_noneautotype/i.test(version) };
32906
32967
  }
32968
+ function resolveFastjsonFromGradleCatalog(buildGradle, libsVersionsToml) {
32969
+ if (!buildGradle || !libsVersionsToml) return null;
32970
+ const librariesMatch = libsVersionsToml.match(
32971
+ /\[libraries\]([\s\S]*?)(?=\n\[|$)/
32972
+ );
32973
+ if (!librariesMatch) return null;
32974
+ const librariesBlock = librariesMatch[1];
32975
+ const moduleForm = librariesBlock.match(
32976
+ /^\s*([\w.-]+)\s*=\s*\{[^}]*\bmodule\s*=\s*"com\.alibaba:fastjson"[^}]*\}/m
32977
+ );
32978
+ const groupNameForm = librariesBlock.match(
32979
+ /^\s*([\w.-]+)\s*=\s*\{[^}]*\bgroup\s*=\s*"com\.alibaba"[^}]*\bname\s*=\s*"fastjson"[^}]*\}/m
32980
+ );
32981
+ const entry = moduleForm ?? groupNameForm;
32982
+ if (!entry) return null;
32983
+ const alias = entry[1];
32984
+ const entryBody = entry[0];
32985
+ const aliasEsc = alias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
32986
+ const aliasRefRe = new RegExp(`\\blibs\\s*\\.\\s*${aliasEsc}\\b`);
32987
+ if (!aliasRefRe.test(buildGradle)) return null;
32988
+ const inlineVersionM = entryBody.match(
32989
+ /\bversion\s*=\s*"([^"$][^"]*)"/
32990
+ );
32991
+ if (inlineVersionM) {
32992
+ const version2 = inlineVersionM[1];
32993
+ return { version: version2, noneAutotype: /_noneautotype/i.test(version2) };
32994
+ }
32995
+ const versionRefM = entryBody.match(/\bversion\.ref\s*=\s*"([^"]+)"/);
32996
+ if (!versionRefM) return null;
32997
+ const versionAlias = versionRefM[1];
32998
+ const versionsMatch = libsVersionsToml.match(
32999
+ /\[versions\]([\s\S]*?)(?=\n\[|$)/
33000
+ );
33001
+ if (!versionsMatch) return null;
33002
+ const versionsBlock = versionsMatch[1];
33003
+ const versionAliasEsc = versionAlias.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
33004
+ const versionLineRe = new RegExp(
33005
+ `^\\s*${versionAliasEsc}\\s*=\\s*"([^"]+)"`,
33006
+ "m"
33007
+ );
33008
+ const versionLine = versionsBlock.match(versionLineRe);
33009
+ if (!versionLine) return null;
33010
+ const version = versionLine[1];
33011
+ return { version, noneAutotype: /_noneautotype/i.test(version) };
33012
+ }
32907
33013
  function resolvePyYamlFromRequirements(requirementsTxt) {
32908
33014
  if (!requirementsTxt) return null;
32909
33015
  for (const rawLine of requirementsTxt.split(/\r?\n/)) {
@@ -33005,7 +33111,8 @@ var DeserializationSafetyGatePass = class {
33005
33111
  const sinks = ctx.hasResult("sink-filter") ? ctx.getResult("sink-filter").sinks : graph.ir.taint.sinks;
33006
33112
  const pomXml = this.dependencyContext?.java?.pomXml;
33007
33113
  const buildGradle = this.dependencyContext?.java?.buildGradle;
33008
- const fastjson = (pomXml ? resolveFastjsonFromPom(pomXml) : null) ?? (buildGradle ? resolveFastjsonFromGradle(buildGradle) : null);
33114
+ const libsVersionsToml = this.dependencyContext?.java?.libsVersionsToml;
33115
+ const fastjson = (pomXml ? resolveFastjsonFromPom(pomXml) : null) ?? (buildGradle ? resolveFastjsonFromGradle(buildGradle) : null) ?? (buildGradle && libsVersionsToml ? resolveFastjsonFromGradleCatalog(buildGradle, libsVersionsToml) : null);
33009
33116
  const fastjsonHardened = fastjson?.noneAutotype === true && !fileReenablesFastjsonAutotype(code);
33010
33117
  const jacksonSafe = !fileEnablesJacksonPolymorphism(code);
33011
33118
  const snakeYamlSafe = fileConfiguresSnakeYamlSafely(code);
@@ -38822,6 +38929,53 @@ var ScanSecretsPass = class {
38822
38929
  }
38823
38930
  };
38824
38931
 
38932
+ // src/analysis/passes/python-receiver-taint-format-pass.ts
38933
+ var PythonReceiverTaintFormatPass = class {
38934
+ name = "python-receiver-taint-format";
38935
+ category = "security";
38936
+ run(ctx) {
38937
+ if (ctx.language !== "python") {
38938
+ return { findingsEmitted: 0 };
38939
+ }
38940
+ const { calls, meta, taint } = ctx.graph.ir;
38941
+ const taintedVarNames = /* @__PURE__ */ new Set();
38942
+ for (const s of taint.sources) {
38943
+ if (typeof s.variable === "string" && s.variable.length > 0) {
38944
+ taintedVarNames.add(s.variable);
38945
+ }
38946
+ }
38947
+ if (taintedVarNames.size === 0) {
38948
+ return { findingsEmitted: 0 };
38949
+ }
38950
+ const seen = /* @__PURE__ */ new Set();
38951
+ let count = 0;
38952
+ for (const call of calls) {
38953
+ if (call.method_name !== "format" && call.method_name !== "format_map") continue;
38954
+ const receiver = call.receiver;
38955
+ if (!receiver) continue;
38956
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(receiver)) continue;
38957
+ if (!taintedVarNames.has(receiver)) continue;
38958
+ const seenKey = `${call.location.line}:${receiver}`;
38959
+ if (seen.has(seenKey)) continue;
38960
+ seen.add(seenKey);
38961
+ ctx.addFinding({
38962
+ id: `format_string-${meta.file}-${call.location.line}-${receiver}-${call.method_name}`,
38963
+ pass: this.name,
38964
+ category: "security",
38965
+ rule_id: "format_string",
38966
+ cwe: "CWE-134",
38967
+ severity: "medium",
38968
+ level: "warning",
38969
+ message: `Format-string vulnerability: the format template \`${receiver}\` is tainted (traces back to a taint source) and used as the receiver of \`${call.method_name}(...)\`. Attacker can leak object attributes via \`{obj.__class__.__mro__[\u2026]}\` chains or crash the process via unbounded specifiers. Use a literal format string and pass user input as an argument instead.`,
38970
+ file: meta.file,
38971
+ line: call.location.line
38972
+ });
38973
+ count++;
38974
+ }
38975
+ return { findingsEmitted: count };
38976
+ }
38977
+ };
38978
+
38825
38979
  // src/analysis/passes/spring4shell-pass.ts
38826
38980
  var CONTROLLER_ANNOTATIONS = /* @__PURE__ */ new Set([
38827
38981
  "Controller",
@@ -43162,6 +43316,8 @@ async function analyze(code, filePath, language, options = {}) {
43162
43316
  if (!disabledPasses.has("library-profile-cwe22-path-gate"))
43163
43317
  pipeline.add(new LibraryProfileCwe22PathGatePass());
43164
43318
  if (!disabledPasses.has("scan-secrets")) pipeline.add(new ScanSecretsPass());
43319
+ if (!disabledPasses.has("python-receiver-taint-format"))
43320
+ pipeline.add(new PythonReceiverTaintFormatPass());
43165
43321
  if (!disabledPasses.has("dead-code")) pipeline.add(new DeadCodePass());
43166
43322
  if (!disabledPasses.has("missing-await")) pipeline.add(new MissingAwaitPass());
43167
43323
  if (!disabledPasses.has("n-plus-one")) pipeline.add(new NPlusOnePass());
@@ -10677,6 +10677,35 @@ var DEFAULT_SOURCES = [
10677
10677
  { method: "get", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
10678
10678
  { method: "hget", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
10679
10679
  { method: "mget", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
10680
+ // --- Serverless transport channels (cognium-dev #213 first slice) ---
10681
+ //
10682
+ // AWS Lambda / API Gateway invocation-event properties. The Lambda
10683
+ // handler signature `(event, context) => …` (JS/TS) or
10684
+ // `def handler(event, context)` (Python) receives an `event` object
10685
+ // whose properties carry the untrusted HTTP-request-shaped payload:
10686
+ //
10687
+ // event.body — request body (string)
10688
+ // event.queryStringParameters — `?a=b` params
10689
+ // event.multiValueQueryStringParameters — `?a=1&a=2` params
10690
+ // event.pathParameters — path template captures
10691
+ // event.headers — request headers
10692
+ // event.multiValueHeaders — repeated headers
10693
+ // event.requestContext — API Gateway request context
10694
+ //
10695
+ // Vercel Serverless Functions and Cloudflare Workers both use `req`
10696
+ // / `request` receivers that are already covered by the Express-
10697
+ // style patterns above (line ~398). This block specifically covers
10698
+ // the `event`-shaped API Gateway convention that those don't reach.
10699
+ { property: "body", object: "event", type: "http_body", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10700
+ { property: "queryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10701
+ { property: "multiValueQueryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10702
+ { property: "pathParameters", object: "event", type: "http_path", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10703
+ { property: "headers", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10704
+ { property: "multiValueHeaders", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10705
+ { property: "body", object: "event", type: "http_body", severity: "high", property_tainted: true, languages: ["python"] },
10706
+ { property: "queryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["python"] },
10707
+ { property: "pathParameters", object: "event", type: "http_path", severity: "high", property_tainted: true, languages: ["python"] },
10708
+ { property: "headers", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["python"] },
10680
10709
  // --- JWT claims (unverified decode — PyJWT / jose / jsonwebtoken / auth0 java-jwt / golang-jwt) ---
10681
10710
  // A JWT's payload is *always* attacker-authored. Even after verification
10682
10711
  // the *contents* of the claims (username, role, custom fields) are not
@@ -11672,6 +11701,20 @@ var DEFAULT_SINKS = [
11672
11701
  // Sandbox/script security
11673
11702
  { method: "onNewInstance", class: "SandboxInterceptor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
11674
11703
  // Java Log Injection (slf4j / logback / java.util.logging) — CWE-117
11704
+ //
11705
+ // Classification decision — cognium-dev #264: Logger receivers stay
11706
+ // as log_injection (CWE-117), NOT format_string (CWE-134). The real
11707
+ // vulnerability with tainted data flowing into Logger.log(fmt, ...)
11708
+ // is log-forgery via CRLF injection, not format-string exploitation.
11709
+ // A genuine format_string vulnerability requires the FORMAT STRING
11710
+ // itself to be attacker-controlled, which is virtually never the
11711
+ // case in Logger APIs (the format string is a literal at the call
11712
+ // site). Adding format_string sinks for these same receivers would
11713
+ // duplicate the existing log_injection findings on every call site
11714
+ // without adding real signal. The rare edge case where a caller
11715
+ // passes `taintedFmt` at arg[0] is still caught by these entries
11716
+ // (via arg_positions[0] on the SLF4J-family methods), classified as
11717
+ // log_injection.
11675
11718
  // Issue #44: log.info/warn/error/debug emit the message argument and any
11676
11719
  // {} format arguments to the log stream. Untrusted input forwarded into
11677
11720
  // these calls allows log forging (newline injection) and downstream log
@@ -10611,6 +10611,35 @@ var DEFAULT_SOURCES = [
10611
10611
  { method: "get", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
10612
10612
  { method: "hget", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
10613
10613
  { method: "mget", class: "Jedis", type: "db_input", severity: "medium", return_tainted: true, languages: ["java"] },
10614
+ // --- Serverless transport channels (cognium-dev #213 first slice) ---
10615
+ //
10616
+ // AWS Lambda / API Gateway invocation-event properties. The Lambda
10617
+ // handler signature `(event, context) => …` (JS/TS) or
10618
+ // `def handler(event, context)` (Python) receives an `event` object
10619
+ // whose properties carry the untrusted HTTP-request-shaped payload:
10620
+ //
10621
+ // event.body — request body (string)
10622
+ // event.queryStringParameters — `?a=b` params
10623
+ // event.multiValueQueryStringParameters — `?a=1&a=2` params
10624
+ // event.pathParameters — path template captures
10625
+ // event.headers — request headers
10626
+ // event.multiValueHeaders — repeated headers
10627
+ // event.requestContext — API Gateway request context
10628
+ //
10629
+ // Vercel Serverless Functions and Cloudflare Workers both use `req`
10630
+ // / `request` receivers that are already covered by the Express-
10631
+ // style patterns above (line ~398). This block specifically covers
10632
+ // the `event`-shaped API Gateway convention that those don't reach.
10633
+ { property: "body", object: "event", type: "http_body", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10634
+ { property: "queryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10635
+ { property: "multiValueQueryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10636
+ { property: "pathParameters", object: "event", type: "http_path", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10637
+ { property: "headers", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10638
+ { property: "multiValueHeaders", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["javascript", "typescript"] },
10639
+ { property: "body", object: "event", type: "http_body", severity: "high", property_tainted: true, languages: ["python"] },
10640
+ { property: "queryStringParameters", object: "event", type: "http_query", severity: "high", property_tainted: true, languages: ["python"] },
10641
+ { property: "pathParameters", object: "event", type: "http_path", severity: "high", property_tainted: true, languages: ["python"] },
10642
+ { property: "headers", object: "event", type: "http_header", severity: "high", property_tainted: true, languages: ["python"] },
10614
10643
  // --- JWT claims (unverified decode — PyJWT / jose / jsonwebtoken / auth0 java-jwt / golang-jwt) ---
10615
10644
  // A JWT's payload is *always* attacker-authored. Even after verification
10616
10645
  // the *contents* of the claims (username, role, custom fields) are not
@@ -11606,6 +11635,20 @@ var DEFAULT_SINKS = [
11606
11635
  // Sandbox/script security
11607
11636
  { method: "onNewInstance", class: "SandboxInterceptor", type: "command_injection", cwe: "CWE-78", severity: "critical", arg_positions: [0] },
11608
11637
  // Java Log Injection (slf4j / logback / java.util.logging) — CWE-117
11638
+ //
11639
+ // Classification decision — cognium-dev #264: Logger receivers stay
11640
+ // as log_injection (CWE-117), NOT format_string (CWE-134). The real
11641
+ // vulnerability with tainted data flowing into Logger.log(fmt, ...)
11642
+ // is log-forgery via CRLF injection, not format-string exploitation.
11643
+ // A genuine format_string vulnerability requires the FORMAT STRING
11644
+ // itself to be attacker-controlled, which is virtually never the
11645
+ // case in Logger APIs (the format string is a literal at the call
11646
+ // site). Adding format_string sinks for these same receivers would
11647
+ // duplicate the existing log_injection findings on every call site
11648
+ // without adding real signal. The rare edge case where a caller
11649
+ // passes `taintedFmt` at arg[0] is still caught by these entries
11650
+ // (via arg_positions[0] on the SLF4J-family methods), classified as
11651
+ // log_injection.
11609
11652
  // Issue #44: log.info/warn/error/debug emit the message argument and any
11610
11653
  // {} format arguments to the log stream. Untrusted input forwarded into
11611
11654
  // these calls allows log forging (newline injection) and downstream log
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circle-ir",
3
- "version": "3.179.0",
3
+ "version": "3.181.0",
4
4
  "description": "High-performance Static Application Security Testing (SAST) library for detecting security vulnerabilities through taint analysis",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",