circle-ir 3.206.0 → 3.209.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.
- package/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +10 -2
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/passes/scan-secrets-pass.d.ts.map +1 -1
- package/dist/analysis/passes/scan-secrets-pass.js +70 -0
- package/dist/analysis/passes/scan-secrets-pass.js.map +1 -1
- package/dist/analysis/passes/sink-filter-pass.d.ts.map +1 -1
- package/dist/analysis/passes/sink-filter-pass.js +42 -0
- package/dist/analysis/passes/sink-filter-pass.js.map +1 -1
- package/dist/browser/circle-ir.js +78 -2
- package/dist/core/circle-ir-core.cjs +10 -2
- package/dist/core/circle-ir-core.js +10 -2
- package/package.json +1 -1
|
@@ -12187,8 +12187,16 @@ var DEFAULT_SINKS = [
|
|
|
12187
12187
|
// node ClientRequest.write, etc.) as xss. Real HTML writers are covered
|
|
12188
12188
|
// by class-scoped entries: PrintWriter.write (line 843), ServletOutputStream.write
|
|
12189
12189
|
// (line 849), JspWriter.write (xss.yaml), Response.write (nodejs.json).
|
|
12190
|
-
|
|
12191
|
-
|
|
12190
|
+
// NOTE (cognium-ai#268): `StringBuilder.append` / `StringBuffer.append` were
|
|
12191
|
+
// registered here as xss sinks, but string construction is NOT an HTML-output
|
|
12192
|
+
// context — the actual sink is wherever the built string is later written to
|
|
12193
|
+
// a response / template (PrintWriter, ServletOutputStream, JspWriter, etc.,
|
|
12194
|
+
// which taint propagation reaches via `sb.toString()`). This was the #1
|
|
12195
|
+
// crit/high FP bucket on the top-100 Java sweep (fires on every append,
|
|
12196
|
+
// incl. constant args). Removed globally: measured 0 OWASP xss true-positive
|
|
12197
|
+
// loss (every xss TP has a real HTML-output sink), and the #244
|
|
12198
|
+
// LibraryProfileXssGatePass already dropped them for `library/*`. Taint still
|
|
12199
|
+
// flows source → StringBuilder → real write sink.
|
|
12192
12200
|
// Wiki/CMS XSS sinks (JSPWiki, Confluence, etc.)
|
|
12193
12201
|
{ method: "handleHyperlinks", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
12194
12202
|
{ method: "handleDiv", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
@@ -32457,6 +32465,8 @@ var SQL_EXEC_METHODS = /* @__PURE__ */ new Set([
|
|
|
32457
32465
|
"addBatch"
|
|
32458
32466
|
]);
|
|
32459
32467
|
var JAVA_SQL_ASSIGN_RE_TEMPLATE = "\\b(?:String|CharSequence|final\\s+String|var)\\s+SQLVAR\\b\\s*=\\s*(.+?);";
|
|
32468
|
+
var REPLACE_ALL_TO_PLACEHOLDER_RE = /\.replaceAll\s*\([\s\S]*?,\s*"[\s,?]*\?[\s,?]*"\s*\)/;
|
|
32469
|
+
var HTML_CONTENT_TYPE_RE = /text\/html|TEXT_HTML/;
|
|
32460
32470
|
var JAVA_INLINE_MATCHES_RE = /\.\s*matches\s*\(\s*"((?:[^"\\]|\\.)*)"\s*\)/g;
|
|
32461
32471
|
function resolveJavaReceiverType(receiver, sinkLine, sourceLines) {
|
|
32462
32472
|
if (!receiver || !/^[A-Za-z_]\w*$/.test(receiver)) return null;
|
|
@@ -33131,6 +33141,18 @@ var SinkFilterPass = class {
|
|
|
33131
33141
|
return true;
|
|
33132
33142
|
});
|
|
33133
33143
|
}
|
|
33144
|
+
if (language === "java") {
|
|
33145
|
+
const sourceLines = ctx.code.split("\n");
|
|
33146
|
+
filtered = filtered.filter((sink) => {
|
|
33147
|
+
if (sink.type !== "sql_injection") return true;
|
|
33148
|
+
if (!SQL_EXEC_METHODS.has(sink.method ?? "")) return true;
|
|
33149
|
+
const sinkLineText = sourceLines[sink.line - 1] ?? "";
|
|
33150
|
+
return !REPLACE_ALL_TO_PLACEHOLDER_RE.test(sinkLineText);
|
|
33151
|
+
});
|
|
33152
|
+
}
|
|
33153
|
+
if (language === "java" && !HTML_CONTENT_TYPE_RE.test(ctx.code)) {
|
|
33154
|
+
filtered = filtered.filter((sink) => !(sink.type === "xss" && sink.method === "body"));
|
|
33155
|
+
}
|
|
33134
33156
|
if (["javascript", "typescript"].includes(language)) {
|
|
33135
33157
|
const sourceLines = ctx.code.split("\n");
|
|
33136
33158
|
filtered = filtered.filter((sink) => {
|
|
@@ -39911,6 +39933,34 @@ function shannonEntropy(s) {
|
|
|
39911
39933
|
return h;
|
|
39912
39934
|
}
|
|
39913
39935
|
var CREDENTIAL_NAME_RE = /(?:key|secret|token|password|passwd|credential|api[_-]?key)/i;
|
|
39936
|
+
var CONNECTION_STRING_RE = /\b([a-z][a-z0-9+.-]{1,20}):\/\/([^\s:/@"'`]*):([^\s:/@"'`]{2,})@/i;
|
|
39937
|
+
var PASSWORD_INTERPOLATION_RE = /\$\{|\$\(|\{\{|%\([^)]*\)[sd]|%[sdvfeg]\b|[{}<>]/i;
|
|
39938
|
+
var PLACEHOLDER_PASSWORD_WORDS = /* @__PURE__ */ new Set([
|
|
39939
|
+
"password",
|
|
39940
|
+
"passwd",
|
|
39941
|
+
"pass",
|
|
39942
|
+
"pwd",
|
|
39943
|
+
"secret",
|
|
39944
|
+
"user",
|
|
39945
|
+
"username",
|
|
39946
|
+
"changeme",
|
|
39947
|
+
"example",
|
|
39948
|
+
"yourpassword",
|
|
39949
|
+
"your_password",
|
|
39950
|
+
"test",
|
|
39951
|
+
"xxx",
|
|
39952
|
+
"xxxx"
|
|
39953
|
+
]);
|
|
39954
|
+
function matchConnectionStringCredential(lineText) {
|
|
39955
|
+
const m = CONNECTION_STRING_RE.exec(lineText);
|
|
39956
|
+
if (!m) return null;
|
|
39957
|
+
const password = m[3];
|
|
39958
|
+
if (/^\d+$/.test(password)) return null;
|
|
39959
|
+
if (PLACEHOLDER_PASSWORD_WORDS.has(password.toLowerCase())) return null;
|
|
39960
|
+
if (PLACEHOLDER_RE.test(password)) return null;
|
|
39961
|
+
if (PASSWORD_INTERPOLATION_RE.test(password)) return null;
|
|
39962
|
+
return { scheme: m[1], match: m[0].substring(0, 60) };
|
|
39963
|
+
}
|
|
39914
39964
|
function findAnnotationLineRanges(code) {
|
|
39915
39965
|
const lines = code.split("\n");
|
|
39916
39966
|
const inAnnotation = /* @__PURE__ */ new Set();
|
|
@@ -40106,6 +40156,32 @@ var ScanSecretsPass = class {
|
|
|
40106
40156
|
});
|
|
40107
40157
|
providerFindings += 1;
|
|
40108
40158
|
}
|
|
40159
|
+
for (let i2 = 0; i2 < lines.length; i2++) {
|
|
40160
|
+
const lineText = lines[i2];
|
|
40161
|
+
const lineNum = i2 + 1;
|
|
40162
|
+
const hit = matchConnectionStringCredential(lineText);
|
|
40163
|
+
if (!hit) continue;
|
|
40164
|
+
const key = `${lineNum}:hardcoded-credential`;
|
|
40165
|
+
if (seen.has(key)) continue;
|
|
40166
|
+
seen.add(key);
|
|
40167
|
+
const dg = applyDemoDowngrade(demoPath, "high", "error");
|
|
40168
|
+
ctx.addFinding({
|
|
40169
|
+
id: `hardcoded-credential-${file}-${lineNum}`,
|
|
40170
|
+
pass: this.name,
|
|
40171
|
+
category: this.category,
|
|
40172
|
+
rule_id: "hardcoded-credential",
|
|
40173
|
+
cwe: "CWE-798",
|
|
40174
|
+
severity: dg.severity,
|
|
40175
|
+
level: dg.level,
|
|
40176
|
+
message: `Hardcoded credential: password embedded in a ${hit.scheme} connection string`,
|
|
40177
|
+
file,
|
|
40178
|
+
line: lineNum,
|
|
40179
|
+
snippet: lineText.trim().substring(0, 120),
|
|
40180
|
+
fix: "Move the credential out of the connection string into an environment variable or secrets manager, and rotate the exposed password.",
|
|
40181
|
+
evidence: { kind: "connection-string", scheme: hit.scheme, match: hit.match }
|
|
40182
|
+
});
|
|
40183
|
+
providerFindings += 1;
|
|
40184
|
+
}
|
|
40109
40185
|
if (hasEntropyCandidate) for (let i2 = 0; i2 < lines.length; i2++) {
|
|
40110
40186
|
const lineText = lines[i2];
|
|
40111
40187
|
const lineNum = i2 + 1;
|
|
@@ -11582,8 +11582,16 @@ var DEFAULT_SINKS = [
|
|
|
11582
11582
|
// node ClientRequest.write, etc.) as xss. Real HTML writers are covered
|
|
11583
11583
|
// by class-scoped entries: PrintWriter.write (line 843), ServletOutputStream.write
|
|
11584
11584
|
// (line 849), JspWriter.write (xss.yaml), Response.write (nodejs.json).
|
|
11585
|
-
|
|
11586
|
-
|
|
11585
|
+
// NOTE (cognium-ai#268): `StringBuilder.append` / `StringBuffer.append` were
|
|
11586
|
+
// registered here as xss sinks, but string construction is NOT an HTML-output
|
|
11587
|
+
// context — the actual sink is wherever the built string is later written to
|
|
11588
|
+
// a response / template (PrintWriter, ServletOutputStream, JspWriter, etc.,
|
|
11589
|
+
// which taint propagation reaches via `sb.toString()`). This was the #1
|
|
11590
|
+
// crit/high FP bucket on the top-100 Java sweep (fires on every append,
|
|
11591
|
+
// incl. constant args). Removed globally: measured 0 OWASP xss true-positive
|
|
11592
|
+
// loss (every xss TP has a real HTML-output sink), and the #244
|
|
11593
|
+
// LibraryProfileXssGatePass already dropped them for `library/*`. Taint still
|
|
11594
|
+
// flows source → StringBuilder → real write sink.
|
|
11587
11595
|
// Wiki/CMS XSS sinks (JSPWiki, Confluence, etc.)
|
|
11588
11596
|
{ method: "handleHyperlinks", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
11589
11597
|
{ method: "handleDiv", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
@@ -11516,8 +11516,16 @@ var DEFAULT_SINKS = [
|
|
|
11516
11516
|
// node ClientRequest.write, etc.) as xss. Real HTML writers are covered
|
|
11517
11517
|
// by class-scoped entries: PrintWriter.write (line 843), ServletOutputStream.write
|
|
11518
11518
|
// (line 849), JspWriter.write (xss.yaml), Response.write (nodejs.json).
|
|
11519
|
-
|
|
11520
|
-
|
|
11519
|
+
// NOTE (cognium-ai#268): `StringBuilder.append` / `StringBuffer.append` were
|
|
11520
|
+
// registered here as xss sinks, but string construction is NOT an HTML-output
|
|
11521
|
+
// context — the actual sink is wherever the built string is later written to
|
|
11522
|
+
// a response / template (PrintWriter, ServletOutputStream, JspWriter, etc.,
|
|
11523
|
+
// which taint propagation reaches via `sb.toString()`). This was the #1
|
|
11524
|
+
// crit/high FP bucket on the top-100 Java sweep (fires on every append,
|
|
11525
|
+
// incl. constant args). Removed globally: measured 0 OWASP xss true-positive
|
|
11526
|
+
// loss (every xss TP has a real HTML-output sink), and the #244
|
|
11527
|
+
// LibraryProfileXssGatePass already dropped them for `library/*`. Taint still
|
|
11528
|
+
// flows source → StringBuilder → real write sink.
|
|
11521
11529
|
// Wiki/CMS XSS sinks (JSPWiki, Confluence, etc.)
|
|
11522
11530
|
{ method: "handleHyperlinks", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
|
11523
11531
|
{ method: "handleDiv", type: "xss", cwe: "CWE-79", severity: "high", arg_positions: [0] },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circle-ir",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.209.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",
|