circle-ir 3.51.0 → 3.53.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/configs/sinks/path.yaml +0 -16
- package/configs/sources/file_sources.yaml +32 -0
- package/dist/analysis/config-loader.d.ts.map +1 -1
- package/dist/analysis/config-loader.js +17 -20
- package/dist/analysis/config-loader.js.map +1 -1
- package/dist/analysis/passes/insecure-cookie-pass.d.ts +23 -23
- package/dist/analysis/passes/insecure-cookie-pass.d.ts.map +1 -1
- package/dist/analysis/passes/insecure-cookie-pass.js +169 -79
- package/dist/analysis/passes/insecure-cookie-pass.js.map +1 -1
- package/dist/analysis/passes/tls-verify-disabled-pass.d.ts +52 -0
- package/dist/analysis/passes/tls-verify-disabled-pass.d.ts.map +1 -0
- package/dist/analysis/passes/tls-verify-disabled-pass.js +247 -0
- package/dist/analysis/passes/tls-verify-disabled-pass.js.map +1 -0
- package/dist/analysis/passes/weak-crypto-pass.d.ts +59 -0
- package/dist/analysis/passes/weak-crypto-pass.d.ts.map +1 -0
- package/dist/analysis/passes/weak-crypto-pass.js +392 -0
- package/dist/analysis/passes/weak-crypto-pass.js.map +1 -0
- package/dist/analysis/passes/weak-hash-pass.d.ts +45 -0
- package/dist/analysis/passes/weak-hash-pass.d.ts.map +1 -0
- package/dist/analysis/passes/weak-hash-pass.js +150 -0
- package/dist/analysis/passes/weak-hash-pass.js.map +1 -0
- package/dist/analysis/passes/weak-random-pass.d.ts +53 -0
- package/dist/analysis/passes/weak-random-pass.d.ts.map +1 -0
- package/dist/analysis/passes/weak-random-pass.js +181 -0
- package/dist/analysis/passes/weak-random-pass.js.map +1 -0
- package/dist/analysis/taint-matcher.d.ts.map +1 -1
- package/dist/analysis/taint-matcher.js +28 -13
- package/dist/analysis/taint-matcher.js.map +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +12 -0
- package/dist/analyzer.js.map +1 -1
- package/dist/browser/circle-ir.js +852 -57
- package/dist/core/circle-ir-core.cjs +25 -26
- package/dist/core/circle-ir-core.js +25 -26
- package/package.json +1 -1
|
@@ -10003,6 +10003,13 @@ var DEFAULT_SOURCES = [
|
|
|
10003
10003
|
{ method: "getFileName", class: "BodyPart", type: "file_input", severity: "high", return_tainted: true },
|
|
10004
10004
|
{ method: "getFileName", class: "MimeBodyPart", type: "file_input", severity: "high", return_tainted: true },
|
|
10005
10005
|
{ method: "getDisposition", class: "Part", type: "file_input", severity: "medium", return_tainted: true },
|
|
10006
|
+
// Archive entry names (Zip-Slip / Tar-Slip CWE-22, issue #52)
|
|
10007
|
+
// entry.getName() returns a path that may contain ../ — flowing into File()/FileOutputStream()
|
|
10008
|
+
// is a classic Zip-Slip vulnerability.
|
|
10009
|
+
{ method: "getName", class: "ZipEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
10010
|
+
{ method: "getName", class: "ZipArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
10011
|
+
{ method: "getName", class: "TarArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
10012
|
+
{ method: "getName", class: "ArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
10006
10013
|
// Command line arguments
|
|
10007
10014
|
{ method: "getArgs", type: "io_input", severity: "high", return_tainted: true },
|
|
10008
10015
|
{ method: "getOptionValue", class: "CommandLine", type: "io_input", severity: "high", return_tainted: true },
|
|
@@ -10437,7 +10444,7 @@ var DEFAULT_SINKS = [
|
|
|
10437
10444
|
{ method: "staticFileLocation", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10438
10445
|
// Zip/archive handling
|
|
10439
10446
|
{ method: "getEntry", class: "ZipFile", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10440
|
-
|
|
10447
|
+
// ZipEntry.getName moved to file_sources.yaml as a taint SOURCE (type=archive_entry, issue #52)
|
|
10441
10448
|
// Resource loading classes (various frameworks)
|
|
10442
10449
|
{ method: "ClassPathResource", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10443
10450
|
{ method: "FileSystemResource", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -10914,26 +10921,16 @@ var DEFAULT_SINKS = [
|
|
|
10914
10921
|
{ method: "get", class: "WebClient", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [] },
|
|
10915
10922
|
{ method: "post", class: "WebClient", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [] },
|
|
10916
10923
|
// =============================================================================
|
|
10917
|
-
//
|
|
10924
|
+
// Config / Absence Vulnerabilities (handled by dedicated pattern passes)
|
|
10918
10925
|
// =============================================================================
|
|
10919
|
-
//
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
// Weak Hash (CWE-328) - MD5/SHA1 are cryptographically broken
|
|
10928
|
-
// Note: Detection requires checking algorithm argument - handled in runner
|
|
10929
|
-
{ method: "getInstance", class: "MessageDigest", type: "weak_hash", cwe: "CWE-328", severity: "medium", arg_positions: [0] },
|
|
10930
|
-
// Weak Crypto (CWE-327) - DES/RC4/Blowfish are weak ciphers
|
|
10931
|
-
// Note: Detection requires checking algorithm argument - handled in runner
|
|
10932
|
-
{ method: "getInstance", class: "Cipher", type: "weak_crypto", cwe: "CWE-327", severity: "high", arg_positions: [0] },
|
|
10933
|
-
{ method: "getInstance", class: "KeyGenerator", type: "weak_crypto", cwe: "CWE-327", severity: "high", arg_positions: [0] },
|
|
10934
|
-
// Insecure Cookie (CWE-614) - cookies without secure/httpOnly flags
|
|
10935
|
-
// Note: Detection requires checking if setSecure(true)/setHttpOnly(true) called - handled in runner
|
|
10936
|
-
{ method: "Cookie", class: "constructor", type: "insecure_cookie", cwe: "CWE-614", severity: "medium", arg_positions: [] },
|
|
10926
|
+
// weak_random → WeakRandomPass (src/analysis/passes/weak-random-pass.ts)
|
|
10927
|
+
// weak_hash → WeakHashPass (src/analysis/passes/weak-hash-pass.ts)
|
|
10928
|
+
// weak_crypto → WeakCryptoPass (src/analysis/passes/weak-crypto-pass.ts)
|
|
10929
|
+
// insecure_cookie → InsecureCookiePass (src/analysis/passes/insecure-cookie-pass.ts)
|
|
10930
|
+
// tls_verify_disabled → TlsVerifyDisabledPass
|
|
10931
|
+
// These patterns are detected by call-site literal inspection, not taint flow,
|
|
10932
|
+
// so they are NOT registered here as sinks (they could never match a "tainted
|
|
10933
|
+
// value flowing into a sink" because the bad value is a hard-coded constant).
|
|
10937
10934
|
// Trust Boundary (CWE-501) - using untrusted data as session attribute NAME
|
|
10938
10935
|
// The vulnerability is attacker controlling which key to use, not the value
|
|
10939
10936
|
{ method: "setAttribute", class: "HttpSession", type: "trust_boundary", cwe: "CWE-501", severity: "medium", arg_positions: [0] },
|
|
@@ -12043,10 +12040,11 @@ function matchesSourcePattern(call, pattern) {
|
|
|
12043
12040
|
return false;
|
|
12044
12041
|
}
|
|
12045
12042
|
if (pattern.class && pattern.class !== "constructor") {
|
|
12046
|
-
if (
|
|
12043
|
+
if (call.receiver_type && call.receiver_type === pattern.class) {
|
|
12044
|
+
} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {
|
|
12045
|
+
} else if (!call.receiver) {
|
|
12047
12046
|
return false;
|
|
12048
|
-
}
|
|
12049
|
-
if (!receiverMightBeClass(call.receiver, pattern.class)) {
|
|
12047
|
+
} else if (!receiverMightBeClass(call.receiver, pattern.class)) {
|
|
12050
12048
|
return false;
|
|
12051
12049
|
}
|
|
12052
12050
|
}
|
|
@@ -12304,13 +12302,14 @@ function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
|
12304
12302
|
if (pattern.class === "constructor") {
|
|
12305
12303
|
return true;
|
|
12306
12304
|
}
|
|
12307
|
-
if (call.
|
|
12305
|
+
if (call.receiver_type && call.receiver_type === pattern.class) {
|
|
12306
|
+
} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {
|
|
12307
|
+
} else if (call.receiver && !receiverMightBeClass(call.receiver, pattern.class)) {
|
|
12308
12308
|
if (typeHierarchy && typeHierarchy.couldBeType(call.receiver, pattern.class)) {
|
|
12309
12309
|
return true;
|
|
12310
12310
|
}
|
|
12311
12311
|
return false;
|
|
12312
|
-
}
|
|
12313
|
-
if (!call.receiver) {
|
|
12312
|
+
} else if (!call.receiver && !call.receiver_type) {
|
|
12314
12313
|
return false;
|
|
12315
12314
|
}
|
|
12316
12315
|
}
|
|
@@ -9937,6 +9937,13 @@ var DEFAULT_SOURCES = [
|
|
|
9937
9937
|
{ method: "getFileName", class: "BodyPart", type: "file_input", severity: "high", return_tainted: true },
|
|
9938
9938
|
{ method: "getFileName", class: "MimeBodyPart", type: "file_input", severity: "high", return_tainted: true },
|
|
9939
9939
|
{ method: "getDisposition", class: "Part", type: "file_input", severity: "medium", return_tainted: true },
|
|
9940
|
+
// Archive entry names (Zip-Slip / Tar-Slip CWE-22, issue #52)
|
|
9941
|
+
// entry.getName() returns a path that may contain ../ — flowing into File()/FileOutputStream()
|
|
9942
|
+
// is a classic Zip-Slip vulnerability.
|
|
9943
|
+
{ method: "getName", class: "ZipEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
9944
|
+
{ method: "getName", class: "ZipArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
9945
|
+
{ method: "getName", class: "TarArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
9946
|
+
{ method: "getName", class: "ArchiveEntry", type: "file_input", severity: "high", return_tainted: true },
|
|
9940
9947
|
// Command line arguments
|
|
9941
9948
|
{ method: "getArgs", type: "io_input", severity: "high", return_tainted: true },
|
|
9942
9949
|
{ method: "getOptionValue", class: "CommandLine", type: "io_input", severity: "high", return_tainted: true },
|
|
@@ -10371,7 +10378,7 @@ var DEFAULT_SINKS = [
|
|
|
10371
10378
|
{ method: "staticFileLocation", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10372
10379
|
// Zip/archive handling
|
|
10373
10380
|
{ method: "getEntry", class: "ZipFile", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10374
|
-
|
|
10381
|
+
// ZipEntry.getName moved to file_sources.yaml as a taint SOURCE (type=archive_entry, issue #52)
|
|
10375
10382
|
// Resource loading classes (various frameworks)
|
|
10376
10383
|
{ method: "ClassPathResource", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
10377
10384
|
{ method: "FileSystemResource", class: "constructor", type: "path_traversal", cwe: "CWE-22", severity: "high", arg_positions: [0] },
|
|
@@ -10848,26 +10855,16 @@ var DEFAULT_SINKS = [
|
|
|
10848
10855
|
{ method: "get", class: "WebClient", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [] },
|
|
10849
10856
|
{ method: "post", class: "WebClient", type: "ssrf", cwe: "CWE-918", severity: "high", arg_positions: [] },
|
|
10850
10857
|
// =============================================================================
|
|
10851
|
-
//
|
|
10858
|
+
// Config / Absence Vulnerabilities (handled by dedicated pattern passes)
|
|
10852
10859
|
// =============================================================================
|
|
10853
|
-
//
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
// Weak Hash (CWE-328) - MD5/SHA1 are cryptographically broken
|
|
10862
|
-
// Note: Detection requires checking algorithm argument - handled in runner
|
|
10863
|
-
{ method: "getInstance", class: "MessageDigest", type: "weak_hash", cwe: "CWE-328", severity: "medium", arg_positions: [0] },
|
|
10864
|
-
// Weak Crypto (CWE-327) - DES/RC4/Blowfish are weak ciphers
|
|
10865
|
-
// Note: Detection requires checking algorithm argument - handled in runner
|
|
10866
|
-
{ method: "getInstance", class: "Cipher", type: "weak_crypto", cwe: "CWE-327", severity: "high", arg_positions: [0] },
|
|
10867
|
-
{ method: "getInstance", class: "KeyGenerator", type: "weak_crypto", cwe: "CWE-327", severity: "high", arg_positions: [0] },
|
|
10868
|
-
// Insecure Cookie (CWE-614) - cookies without secure/httpOnly flags
|
|
10869
|
-
// Note: Detection requires checking if setSecure(true)/setHttpOnly(true) called - handled in runner
|
|
10870
|
-
{ method: "Cookie", class: "constructor", type: "insecure_cookie", cwe: "CWE-614", severity: "medium", arg_positions: [] },
|
|
10860
|
+
// weak_random → WeakRandomPass (src/analysis/passes/weak-random-pass.ts)
|
|
10861
|
+
// weak_hash → WeakHashPass (src/analysis/passes/weak-hash-pass.ts)
|
|
10862
|
+
// weak_crypto → WeakCryptoPass (src/analysis/passes/weak-crypto-pass.ts)
|
|
10863
|
+
// insecure_cookie → InsecureCookiePass (src/analysis/passes/insecure-cookie-pass.ts)
|
|
10864
|
+
// tls_verify_disabled → TlsVerifyDisabledPass
|
|
10865
|
+
// These patterns are detected by call-site literal inspection, not taint flow,
|
|
10866
|
+
// so they are NOT registered here as sinks (they could never match a "tainted
|
|
10867
|
+
// value flowing into a sink" because the bad value is a hard-coded constant).
|
|
10871
10868
|
// Trust Boundary (CWE-501) - using untrusted data as session attribute NAME
|
|
10872
10869
|
// The vulnerability is attacker controlling which key to use, not the value
|
|
10873
10870
|
{ method: "setAttribute", class: "HttpSession", type: "trust_boundary", cwe: "CWE-501", severity: "medium", arg_positions: [0] },
|
|
@@ -11977,10 +11974,11 @@ function matchesSourcePattern(call, pattern) {
|
|
|
11977
11974
|
return false;
|
|
11978
11975
|
}
|
|
11979
11976
|
if (pattern.class && pattern.class !== "constructor") {
|
|
11980
|
-
if (
|
|
11977
|
+
if (call.receiver_type && call.receiver_type === pattern.class) {
|
|
11978
|
+
} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {
|
|
11979
|
+
} else if (!call.receiver) {
|
|
11981
11980
|
return false;
|
|
11982
|
-
}
|
|
11983
|
-
if (!receiverMightBeClass(call.receiver, pattern.class)) {
|
|
11981
|
+
} else if (!receiverMightBeClass(call.receiver, pattern.class)) {
|
|
11984
11982
|
return false;
|
|
11985
11983
|
}
|
|
11986
11984
|
}
|
|
@@ -12238,13 +12236,14 @@ function matchesSinkPattern(call, pattern, typeHierarchy, language) {
|
|
|
12238
12236
|
if (pattern.class === "constructor") {
|
|
12239
12237
|
return true;
|
|
12240
12238
|
}
|
|
12241
|
-
if (call.
|
|
12239
|
+
if (call.receiver_type && call.receiver_type === pattern.class) {
|
|
12240
|
+
} else if (call.receiver_type_fqn && call.receiver_type_fqn.endsWith("." + pattern.class)) {
|
|
12241
|
+
} else if (call.receiver && !receiverMightBeClass(call.receiver, pattern.class)) {
|
|
12242
12242
|
if (typeHierarchy && typeHierarchy.couldBeType(call.receiver, pattern.class)) {
|
|
12243
12243
|
return true;
|
|
12244
12244
|
}
|
|
12245
12245
|
return false;
|
|
12246
|
-
}
|
|
12247
|
-
if (!call.receiver) {
|
|
12246
|
+
} else if (!call.receiver && !call.receiver_type) {
|
|
12248
12247
|
return false;
|
|
12249
12248
|
}
|
|
12250
12249
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circle-ir",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.53.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",
|