circle-ir 3.126.0 → 3.129.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.
@@ -23650,6 +23650,10 @@ var LanguageSourcesPass = class {
23650
23650
  if (language === "go") {
23651
23651
  additionalSanitizers.push(...findGoMapAllowlistGuardSanitizers(code));
23652
23652
  additionalSanitizers.push(...findGoHtmlTemplateImportSanitizers(code));
23653
+ const goMisconfigFindings = findGoPatternFindings(code, graph.ir.meta.file);
23654
+ for (const finding of goMisconfigFindings) {
23655
+ ctx.addFinding(finding);
23656
+ }
23653
23657
  }
23654
23658
  if (language === "python") {
23655
23659
  additionalSanitizers.push(...findPythonNetlocAllowlistGuardSanitizers(code));
@@ -23657,6 +23661,7 @@ var LanguageSourcesPass = class {
23657
23661
  additionalSanitizers.push(...findPythonRegexAllowlistWrapperSanitizers(code));
23658
23662
  additionalSanitizers.push(...findPythonSetMembershipXssGuardSanitizers(code));
23659
23663
  additionalSanitizers.push(...findPythonDefusedXmlSanitizers(code));
23664
+ additionalSanitizers.push(...findPythonJinjaAutoescapeSanitizers(code));
23660
23665
  const pyMisconfigFindings = findPythonPatternFindings(code, graph.ir.meta.file);
23661
23666
  for (const finding of pyMisconfigFindings) {
23662
23667
  ctx.addFinding(finding);
@@ -23665,10 +23670,23 @@ var LanguageSourcesPass = class {
23665
23670
  if (language === "rust") {
23666
23671
  additionalSanitizers.push(...findRustSetAllowlistGuardSanitizers(code));
23667
23672
  additionalSanitizers.push(...findRustCanonicalizeGuardSanitizers(code));
23673
+ additionalSanitizers.push(...findRustArgvCommandSanitizers(code));
23668
23674
  const rustMisconfigFindings = findRustPatternFindings(code, graph.ir.meta.file);
23669
23675
  for (const finding of rustMisconfigFindings) {
23670
23676
  ctx.addFinding(finding);
23671
23677
  }
23678
+ for (const finding of findRustHardcodedCredentialFindings(code, graph.ir.meta.file)) {
23679
+ ctx.addFinding(finding);
23680
+ }
23681
+ for (const finding of findRustInsecureCookieFindings(code, graph.ir.meta.file)) {
23682
+ ctx.addFinding(finding);
23683
+ }
23684
+ for (const finding of findRustJwtVerifyDisabledFindings(code, graph.ir.meta.file)) {
23685
+ ctx.addFinding(finding);
23686
+ }
23687
+ for (const finding of findRustWeakCryptoEcbFindings(code, graph.ir.meta.file)) {
23688
+ ctx.addFinding(finding);
23689
+ }
23672
23690
  }
23673
23691
  if (language === "javascript" || language === "typescript" || language === "htmljs") {
23674
23692
  additionalSanitizers.push(...findJsSafeJsonParseSanitizers(code));
@@ -23676,9 +23694,20 @@ var LanguageSourcesPass = class {
23676
23694
  additionalSanitizers.push(...findJsCsvFormulaPrefixSanitizers(code));
23677
23695
  additionalSanitizers.push(...findJsWrapperFunctionSanitizers(code));
23678
23696
  additionalSanitizers.push(...findJsSsrfAllowlistGuardSanitizers(code));
23697
+ for (const finding of findJsPatternFindings(code, graph.ir.meta.file)) {
23698
+ ctx.addFinding(finding);
23699
+ }
23679
23700
  }
23680
23701
  if (language === "java") {
23681
23702
  additionalSanitizers.push(...findJavaSafeJsonParseSanitizers(code));
23703
+ additionalSanitizers.push(
23704
+ ...findJavaPathNormalizeStartsWithGuardSanitizers(code)
23705
+ );
23706
+ additionalSanitizers.push(...findJavaInlineCrlfStripLogSanitizers(code));
23707
+ additionalSanitizers.push(...findJavaArgvFormExecSanitizers(code));
23708
+ for (const finding of findJavaPatternFindings(code, graph.ir.meta.file)) {
23709
+ ctx.addFinding(finding);
23710
+ }
23682
23711
  }
23683
23712
  if (language === "python" || language === "javascript" || language === "typescript" || language === "go") {
23684
23713
  const exfilFindings = findExternalSecretExfiltrationFindings(
@@ -25425,6 +25454,136 @@ function findJsSsrfAllowlistGuardSanitizers(code) {
25425
25454
  }
25426
25455
  return sanitizers;
25427
25456
  }
25457
+ function findJavaPathNormalizeStartsWithGuardSanitizers(code) {
25458
+ const sanitizers = [];
25459
+ const lines = code.split("\n");
25460
+ const resolveNormalizeRe = /\b([A-Za-z_]\w*)\s*=\s*([A-Za-z_]\w*)\s*\.\s*resolve\s*\([^)]*\)\s*\.\s*normalize\s*\(\s*\)/;
25461
+ const startsWithGuardRe = (varName, rootName) => new RegExp(
25462
+ `if\\s*\\(\\s*!\\s*${varName}\\s*\\.\\s*startsWith\\s*\\(\\s*${rootName}\\s*\\)\\s*\\)`
25463
+ );
25464
+ const terminatorRe = /\b(throw|return)\b/;
25465
+ const candidates = [];
25466
+ for (let i2 = 0; i2 < lines.length; i2++) {
25467
+ const m = resolveNormalizeRe.exec(lines[i2]);
25468
+ if (!m) continue;
25469
+ candidates.push({ line: i2 + 1, fullVar: m[1], rootVar: m[2] });
25470
+ }
25471
+ if (candidates.length === 0) return sanitizers;
25472
+ for (const c of candidates) {
25473
+ const guardRe = startsWithGuardRe(c.fullVar, c.rootVar);
25474
+ let guardLine = -1;
25475
+ for (let l = c.line; l < Math.min(lines.length, c.line + 6); l++) {
25476
+ if (!guardRe.test(lines[l])) continue;
25477
+ if (terminatorRe.test(lines[l]) || l + 1 < lines.length && terminatorRe.test(lines[l + 1])) {
25478
+ guardLine = l + 1;
25479
+ break;
25480
+ }
25481
+ }
25482
+ if (guardLine < 0) continue;
25483
+ const varRefRe = new RegExp(`\\b${c.fullVar}\\b`);
25484
+ sanitizers.push({
25485
+ type: "java_path_normalize_startswith_guard",
25486
+ method: "normalize",
25487
+ line: c.line,
25488
+ sanitizes: ["path_traversal", "external_taint_escape"]
25489
+ });
25490
+ for (let l = c.line; l < lines.length; l++) {
25491
+ if (!varRefRe.test(lines[l])) continue;
25492
+ sanitizers.push({
25493
+ type: "java_path_normalize_startswith_guard",
25494
+ method: "normalize",
25495
+ line: l + 1,
25496
+ sanitizes: ["path_traversal", "external_taint_escape"]
25497
+ });
25498
+ }
25499
+ }
25500
+ return sanitizers;
25501
+ }
25502
+ function findJavaInlineCrlfStripLogSanitizers(code) {
25503
+ const sanitizers = [];
25504
+ const lines = code.split("\n");
25505
+ const logCallStart = /\b(?:log|logger|LOG|LOGGER|slog|LOGGER_)\s*\.\s*(?:info|warn|error|debug|trace|fatal|severe|warning|fine|finer|finest|config)\s*\(/;
25506
+ const crlfReplaceAll = /\.\s*replaceAll\s*\(\s*"\[[^"]*\\\\?[rnt][^"]*\]"/;
25507
+ const crlfReplaceChar = /\.\s*replace\s*\(\s*'(?:\\\\?[rnt])'\s*,/;
25508
+ for (let i2 = 0; i2 < lines.length; i2++) {
25509
+ const text = lines[i2];
25510
+ if (!logCallStart.test(text)) continue;
25511
+ if (!crlfReplaceAll.test(text) && !crlfReplaceChar.test(text)) continue;
25512
+ sanitizers.push({
25513
+ type: "java_inline_crlf_strip_log",
25514
+ method: "replaceAll",
25515
+ line: i2 + 1,
25516
+ sanitizes: ["log_injection", "external_taint_escape"]
25517
+ });
25518
+ }
25519
+ return sanitizers;
25520
+ }
25521
+ function findJavaArgvFormExecSanitizers(code) {
25522
+ const sanitizers = [];
25523
+ const lines = code.split("\n");
25524
+ const argvExecRe = /\.\s*exec\s*\(\s*new\s+String\s*\[\s*\]\s*\{/;
25525
+ const argvPbRe = /\bnew\s+ProcessBuilder\s*\(\s*new\s+String\s*\[\s*\]\s*\{/;
25526
+ for (let i2 = 0; i2 < lines.length; i2++) {
25527
+ const text = lines[i2];
25528
+ if (!argvExecRe.test(text) && !argvPbRe.test(text)) continue;
25529
+ sanitizers.push({
25530
+ type: "java_argv_form_exec",
25531
+ method: "exec",
25532
+ line: i2 + 1,
25533
+ sanitizes: ["command_injection", "external_taint_escape"]
25534
+ });
25535
+ }
25536
+ return sanitizers;
25537
+ }
25538
+ function findRustArgvCommandSanitizers(code) {
25539
+ const sanitizers = [];
25540
+ const lines = code.split("\n");
25541
+ const argvCommandRe = /\bCommand\s*::\s*new\s*\(\s*"[^"]*"\s*\)\s*\.\s*arg\s*\(/;
25542
+ const shellArgvRe = /\bCommand\s*::\s*new\s*\(\s*"(?:sh|bash|zsh|ksh|dash|cmd(?:\.exe)?|powershell|pwsh)"\s*\)\s*\.\s*arg\s*\(\s*"-c"/;
25543
+ for (let i2 = 0; i2 < lines.length; i2++) {
25544
+ const text = lines[i2];
25545
+ if (!argvCommandRe.test(text)) continue;
25546
+ if (shellArgvRe.test(text)) continue;
25547
+ sanitizers.push({
25548
+ type: "rust_argv_command",
25549
+ method: "arg",
25550
+ line: i2 + 1,
25551
+ sanitizes: ["command_injection", "external_taint_escape"]
25552
+ });
25553
+ }
25554
+ return sanitizers;
25555
+ }
25556
+ function findPythonJinjaAutoescapeSanitizers(code) {
25557
+ const sanitizers = [];
25558
+ const lines = code.split("\n");
25559
+ const envAssignRe = /\b([A-Za-z_]\w*)\s*=\s*Environment\s*\(/;
25560
+ const autoescapeOnRe = /\bautoescape\s*=/;
25561
+ const autoescapeOffRe = /\bautoescape\s*=\s*(?:False|None|0)\b/;
25562
+ const envVars = /* @__PURE__ */ new Set();
25563
+ for (let i2 = 0; i2 < lines.length; i2++) {
25564
+ const m = envAssignRe.exec(lines[i2]);
25565
+ if (!m) continue;
25566
+ if (!autoescapeOnRe.test(lines[i2])) continue;
25567
+ if (autoescapeOffRe.test(lines[i2])) continue;
25568
+ envVars.add(m[1]);
25569
+ }
25570
+ if (envVars.size === 0) return sanitizers;
25571
+ for (const envVar of envVars) {
25572
+ const renderChainRe = new RegExp(
25573
+ `\\b${envVar}\\s*\\.\\s*get_template\\s*\\([^)]*\\)\\s*\\.\\s*render\\s*\\(`
25574
+ );
25575
+ for (let i2 = 0; i2 < lines.length; i2++) {
25576
+ if (!renderChainRe.test(lines[i2])) continue;
25577
+ sanitizers.push({
25578
+ type: "python_jinja_autoescape",
25579
+ method: "render",
25580
+ line: i2 + 1,
25581
+ sanitizes: ["xss", "external_taint_escape"]
25582
+ });
25583
+ }
25584
+ }
25585
+ return sanitizers;
25586
+ }
25428
25587
  function collectEnvSecretVars(lines, language) {
25429
25588
  const out2 = /* @__PURE__ */ new Map();
25430
25589
  for (let i2 = 0; i2 < lines.length; i2++) {
@@ -25807,6 +25966,252 @@ function findRustPatternFindings(code, file) {
25807
25966
  }
25808
25967
  return out2;
25809
25968
  }
25969
+ function findRustHardcodedCredentialFindings(code, file) {
25970
+ const out2 = [];
25971
+ const lines = code.split("\n");
25972
+ const re = /\b(?:pub\s+)?(?:const|static)\s+([A-Z][A-Z0-9_]*)\s*:\s*&\s*'?[a-z_]*\s*str\s*=\s*"([^"]+)"/;
25973
+ const nameRe = /(?:^|_)(?:API[_]?KEY|SECRET|TOKEN|PASSWORD|PASSWD|PWD|AUTH)(?:_|$)/i;
25974
+ for (let i2 = 0; i2 < lines.length; i2++) {
25975
+ const raw = lines[i2];
25976
+ const trimmed = raw.trim();
25977
+ if (!trimmed || trimmed.startsWith("//")) continue;
25978
+ const m = trimmed.match(re);
25979
+ if (!m) continue;
25980
+ const name2 = m[1];
25981
+ const value = m[2];
25982
+ if (!nameRe.test(name2)) continue;
25983
+ if (value.length < 8) continue;
25984
+ if (/^(?:xxx|todo|fixme|placeholder|changeme)/i.test(value)) continue;
25985
+ out2.push({
25986
+ id: `hardcoded-credential-${file}-${i2 + 1}`,
25987
+ pass: "language-sources",
25988
+ category: "security",
25989
+ rule_id: "hardcoded-credential",
25990
+ cwe: "CWE-798",
25991
+ severity: "high",
25992
+ level: "error",
25993
+ message: `Hardcoded credential: const ${name2} contains a literal secret value`,
25994
+ file,
25995
+ line: i2 + 1,
25996
+ snippet: trimmed.substring(0, 100)
25997
+ });
25998
+ }
25999
+ return out2;
26000
+ }
26001
+ function findRustInsecureCookieFindings(code, file) {
26002
+ const out2 = [];
26003
+ const lines = code.split("\n");
26004
+ const builderRe = /\bCookie\s*::\s*build\s*\(/;
26005
+ const insecureFlagRe = /\.\s*(?:secure|http_only)\s*\(\s*false\s*\)/;
26006
+ for (let i2 = 0; i2 < lines.length; i2++) {
26007
+ const raw = lines[i2];
26008
+ const trimmed = raw.trim();
26009
+ if (!trimmed || trimmed.startsWith("//")) continue;
26010
+ if (!builderRe.test(trimmed)) continue;
26011
+ if (!insecureFlagRe.test(trimmed)) continue;
26012
+ out2.push({
26013
+ id: `insecure-cookie-${file}-${i2 + 1}`,
26014
+ pass: "language-sources",
26015
+ category: "security",
26016
+ rule_id: "insecure-cookie",
26017
+ cwe: "CWE-1004",
26018
+ severity: "medium",
26019
+ level: "warning",
26020
+ message: "Insecure cookie: Cookie::build chain disables Secure / HttpOnly flag(s)",
26021
+ file,
26022
+ line: i2 + 1,
26023
+ snippet: trimmed.substring(0, 100)
26024
+ });
26025
+ }
26026
+ return out2;
26027
+ }
26028
+ function findRustJwtVerifyDisabledFindings(code, file) {
26029
+ const out2 = [];
26030
+ const lines = code.split("\n");
26031
+ const re = /\.\s*insecure_disable_signature_validation\s*\(/;
26032
+ for (let i2 = 0; i2 < lines.length; i2++) {
26033
+ const raw = lines[i2];
26034
+ const trimmed = raw.trim();
26035
+ if (!trimmed || trimmed.startsWith("//")) continue;
26036
+ if (!re.test(trimmed)) continue;
26037
+ out2.push({
26038
+ id: `jwt-verify-disabled-${file}-${i2 + 1}`,
26039
+ pass: "language-sources",
26040
+ category: "security",
26041
+ rule_id: "jwt-verify-disabled",
26042
+ cwe: "CWE-347",
26043
+ severity: "critical",
26044
+ level: "error",
26045
+ message: "JWT signature verification disabled: Validation::insecure_disable_signature_validation() forfeits signature enforcement",
26046
+ file,
26047
+ line: i2 + 1,
26048
+ snippet: trimmed.substring(0, 100)
26049
+ });
26050
+ }
26051
+ return out2;
26052
+ }
26053
+ function findRustWeakCryptoEcbFindings(code, file) {
26054
+ const out2 = [];
26055
+ const lines = code.split("\n");
26056
+ const ctorRe = /\bAes(?:128|192|256)(?:Ecb)?\s*::\s*new\s*\(/;
26057
+ const blockOpRe = /\.\s*(encrypt_block|decrypt_block)\s*\(/;
26058
+ let sawCtor = false;
26059
+ for (const line of lines) {
26060
+ if (ctorRe.test(line)) {
26061
+ sawCtor = true;
26062
+ break;
26063
+ }
26064
+ }
26065
+ if (!sawCtor) return out2;
26066
+ for (let i2 = 0; i2 < lines.length; i2++) {
26067
+ const raw = lines[i2];
26068
+ const trimmed = raw.trim();
26069
+ if (!trimmed || trimmed.startsWith("//")) continue;
26070
+ if (!blockOpRe.test(trimmed)) continue;
26071
+ out2.push({
26072
+ id: `weak-crypto-${file}-${i2 + 1}`,
26073
+ pass: "language-sources",
26074
+ category: "security",
26075
+ rule_id: "weak-crypto",
26076
+ cwe: "CWE-327",
26077
+ severity: "high",
26078
+ level: "error",
26079
+ message: "Weak crypto (ECB mode): raw Aes::encrypt_block/decrypt_block leaks repeating-block patterns. Use AES-GCM, AES-CTR, or AES-CBC with an HMAC.",
26080
+ file,
26081
+ line: i2 + 1,
26082
+ snippet: trimmed.substring(0, 100)
26083
+ });
26084
+ }
26085
+ return out2;
26086
+ }
26087
+ function findJavaPatternFindings(code, file) {
26088
+ const out2 = [];
26089
+ const lines = code.split("\n");
26090
+ const jwtDecodeRe = /\bJWT\s*\.\s*decode\s*\(/;
26091
+ for (let i2 = 0; i2 < lines.length; i2++) {
26092
+ const raw = lines[i2];
26093
+ const trimmed = raw.trim();
26094
+ if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("*")) continue;
26095
+ if (!jwtDecodeRe.test(trimmed)) continue;
26096
+ if (/\.\s*verify\s*\(/.test(trimmed)) continue;
26097
+ out2.push({
26098
+ id: `jwt-verify-disabled-${file}-${i2 + 1}-decode`,
26099
+ pass: "language-sources",
26100
+ category: "security",
26101
+ rule_id: "jwt-verify-disabled",
26102
+ cwe: "CWE-347",
26103
+ severity: "critical",
26104
+ level: "error",
26105
+ message: "JWT signature not verified: auth0 `JWT.decode(token)` parses without checking the signature. Use `JWT.require(<algorithm>).build().verify(token)` to enforce verification.",
26106
+ file,
26107
+ line: i2 + 1,
26108
+ snippet: trimmed.substring(0, 100)
26109
+ });
26110
+ }
26111
+ const anonStartRe = /\bnew\s+X509TrustManager\s*\(\s*\)\s*\{/;
26112
+ const checkServerSig = /\bcheckServerTrusted\s*\([^)]*\)\s*(?:throws\s+[^\{]*)?\{\s*\}/;
26113
+ for (let i2 = 0; i2 < lines.length; i2++) {
26114
+ const raw = lines[i2];
26115
+ if (!anonStartRe.test(raw)) continue;
26116
+ const end = Math.min(lines.length, i2 + 16);
26117
+ let foundAt = -1;
26118
+ for (let j = i2; j < end; j++) {
26119
+ if (checkServerSig.test(lines[j])) {
26120
+ foundAt = j;
26121
+ break;
26122
+ }
26123
+ }
26124
+ if (foundAt < 0) continue;
26125
+ out2.push({
26126
+ id: `tls-verify-disabled-${file}-${foundAt + 1}`,
26127
+ pass: "language-sources",
26128
+ category: "security",
26129
+ rule_id: "tls-verify-disabled",
26130
+ cwe: "CWE-295",
26131
+ severity: "high",
26132
+ level: "error",
26133
+ message: "TLS certificate verification disabled: anonymous X509TrustManager with empty checkServerTrusted body accepts every certificate.",
26134
+ file,
26135
+ line: foundAt + 1,
26136
+ snippet: lines[foundAt].trim().substring(0, 100)
26137
+ });
26138
+ }
26139
+ return out2;
26140
+ }
26141
+ function findGoPatternFindings(code, file) {
26142
+ const out2 = [];
26143
+ const lines = code.split("\n");
26144
+ const cipherVars = /* @__PURE__ */ new Set();
26145
+ const ctorRe = /\b([a-zA-Z_]\w*)\s*(?:,\s*[a-zA-Z_]\w*)?\s*:?=\s*aes\.NewCipher\s*\(/;
26146
+ for (const line of lines) {
26147
+ const m = line.match(ctorRe);
26148
+ if (m) cipherVars.add(m[1]);
26149
+ }
26150
+ if (cipherVars.size === 0) return out2;
26151
+ for (const v of Array.from(cipherVars)) {
26152
+ const wrapRe = new RegExp(
26153
+ `\\bcipher\\.New(?:GCM|CBCEncrypter|CBCDecrypter|CTR|OFB|CFBEncrypter|CFBDecrypter)\\s*\\(\\s*${v}\\b`
26154
+ );
26155
+ for (const line of lines) {
26156
+ if (wrapRe.test(line)) {
26157
+ cipherVars.delete(v);
26158
+ break;
26159
+ }
26160
+ }
26161
+ }
26162
+ if (cipherVars.size === 0) return out2;
26163
+ for (let i2 = 0; i2 < lines.length; i2++) {
26164
+ const raw = lines[i2];
26165
+ const trimmed = raw.trim();
26166
+ if (!trimmed || trimmed.startsWith("//")) continue;
26167
+ for (const v of cipherVars) {
26168
+ const opRe = new RegExp(`\\b${v}\\s*\\.\\s*(?:Encrypt|Decrypt)\\s*\\(`);
26169
+ if (!opRe.test(trimmed)) continue;
26170
+ out2.push({
26171
+ id: `weak-crypto-${file}-${i2 + 1}`,
26172
+ pass: "language-sources",
26173
+ category: "security",
26174
+ rule_id: "weak-crypto",
26175
+ cwe: "CWE-327",
26176
+ severity: "high",
26177
+ level: "error",
26178
+ message: "Weak crypto (ECB mode): raw aes.Cipher.Encrypt/Decrypt on a block leaks repeating-block patterns. Wrap with cipher.NewGCM, cipher.NewCTR, or cipher.NewCBCEncrypter + HMAC.",
26179
+ file,
26180
+ line: i2 + 1,
26181
+ snippet: trimmed.substring(0, 100)
26182
+ });
26183
+ break;
26184
+ }
26185
+ }
26186
+ return out2;
26187
+ }
26188
+ function findJsPatternFindings(code, file) {
26189
+ const out2 = [];
26190
+ const lines = code.split("\n");
26191
+ const parseRe = /\blibxml(?:js)?\s*\.\s*parseXml(?:String)?\s*\(/;
26192
+ const noentTrueRe = /\bnoent\s*:\s*true\b/;
26193
+ for (let i2 = 0; i2 < lines.length; i2++) {
26194
+ const raw = lines[i2];
26195
+ const trimmed = raw.trim();
26196
+ if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("*")) continue;
26197
+ if (!parseRe.test(trimmed)) continue;
26198
+ if (!noentTrueRe.test(trimmed)) continue;
26199
+ out2.push({
26200
+ id: `xml-entity-expansion-${file}-${i2 + 1}`,
26201
+ pass: "language-sources",
26202
+ category: "security",
26203
+ rule_id: "xml-entity-expansion",
26204
+ cwe: "CWE-611",
26205
+ severity: "high",
26206
+ level: "error",
26207
+ message: "XML external entity resolution enabled: libxmljs parseXml called with `noent: true` resolves external entities (XXE / billion-laughs). Omit the flag or set `noent: false`.",
26208
+ file,
26209
+ line: i2 + 1,
26210
+ snippet: trimmed.substring(0, 100)
26211
+ });
26212
+ }
26213
+ return out2;
26214
+ }
25810
26215
 
25811
26216
  // src/analysis/passes/sink-filter-pass.ts
25812
26217
  var JS_XSS_SANITIZERS = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "circle-ir",
3
- "version": "3.126.0",
3
+ "version": "3.129.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",