pinata-security-cli 0.5.3 → 0.6.1
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/README.md +39 -2
- package/dist/cli/index.js +2423 -1909
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +40 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/package.json +8 -1
- package/src/categories/definitions/concurrency/idempotency-missing.yml +5 -5
- package/src/categories/definitions/concurrency/race-condition.yml +2 -2
- package/src/categories/definitions/data/data-race.yml +15 -18
- package/src/categories/definitions/data/encoding-mismatch.yml +4 -4
- package/src/categories/definitions/data/null-handling.yml +8 -23
- package/src/categories/definitions/input/boundary-testing.yml +12 -40
- package/src/categories/definitions/input/injection-fuzzing.yml +19 -0
- package/src/categories/definitions/input/null-undefined.yml +11 -39
- package/src/categories/definitions/network/connection-failure.yml +9 -3
- package/src/categories/definitions/resource/memory-leak.yml +15 -17
- package/src/categories/definitions/security/auth-failures.yml +8 -0
- package/src/categories/definitions/security/command-injection.yml +17 -0
- package/src/categories/definitions/security/csrf.yml +19 -0
- package/src/categories/definitions/security/data-exposure.yml +24 -0
- package/src/categories/definitions/security/dependency-risks.yml +6 -6
- package/src/categories/definitions/security/deserialization.yml +44 -0
- package/src/categories/definitions/security/file-upload.yml +39 -0
- package/src/categories/definitions/security/ldap-injection.yml +23 -0
- package/src/categories/definitions/security/path-traversal.yml +13 -0
- package/src/categories/definitions/security/prompt-injection.yml +14 -0
- package/src/categories/definitions/security/sql-injection.yml +30 -0
- package/src/categories/definitions/security/ssrf.yml +60 -0
- package/src/categories/definitions/security/xss.yml +36 -0
- package/src/categories/definitions/security/xxe.yml +32 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinata-security-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "AI-powered test coverage analysis and generation tool. Find security blind spots before attackers do.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -75,17 +75,24 @@
|
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@eslint/js": "^9.39.2",
|
|
78
|
+
"@stryker-mutator/core": "^9.5.1",
|
|
79
|
+
"@stryker-mutator/typescript-checker": "^9.5.1",
|
|
80
|
+
"@stryker-mutator/vitest-runner": "^9.5.1",
|
|
81
|
+
"@types/express": "^5.0.6",
|
|
78
82
|
"@types/js-yaml": "^4.0.9",
|
|
79
83
|
"@types/minimatch": "^5.1.2",
|
|
80
84
|
"@types/node": "^20.14.10",
|
|
85
|
+
"@types/supertest": "^7.2.0",
|
|
81
86
|
"@typescript-eslint/eslint-plugin": "^7.16.0",
|
|
82
87
|
"@typescript-eslint/parser": "^7.16.0",
|
|
83
88
|
"@vitest/coverage-v8": "^4.0.18",
|
|
84
89
|
"eslint": "^8.57.1",
|
|
85
90
|
"eslint-config-prettier": "^9.1.0",
|
|
86
91
|
"eslint-plugin-import": "^2.29.1",
|
|
92
|
+
"express": "^5.2.1",
|
|
87
93
|
"fast-check": "^4.5.3",
|
|
88
94
|
"prettier": "^3.3.3",
|
|
95
|
+
"supertest": "^7.2.2",
|
|
89
96
|
"tsup": "^8.1.0",
|
|
90
97
|
"tsx": "^4.21.0",
|
|
91
98
|
"typescript": "^5.5.3",
|
|
@@ -35,8 +35,8 @@ detectionPatterns:
|
|
|
35
35
|
type: regex
|
|
36
36
|
language: python
|
|
37
37
|
pattern: "\\+=\\s*1|counter\\s*\\+|increment\\("
|
|
38
|
-
confidence:
|
|
39
|
-
description: Detects counter increments (
|
|
38
|
+
confidence: medium
|
|
39
|
+
description: Detects counter increments (may need idempotency guards in retry contexts)
|
|
40
40
|
|
|
41
41
|
- id: python-payment-no-idem
|
|
42
42
|
type: regex
|
|
@@ -69,9 +69,9 @@ detectionPatterns:
|
|
|
69
69
|
- id: ts-counter-update
|
|
70
70
|
type: regex
|
|
71
71
|
language: typescript
|
|
72
|
-
pattern: "
|
|
73
|
-
confidence:
|
|
74
|
-
description: Detects counter updates
|
|
72
|
+
pattern: "\\$inc|\\$push(?!.*idempotency|.*idempotent)"
|
|
73
|
+
confidence: medium
|
|
74
|
+
description: Detects MongoDB counter/array updates without idempotency
|
|
75
75
|
|
|
76
76
|
- id: ts-webhook-no-dedup
|
|
77
77
|
type: regex
|
|
@@ -65,9 +65,9 @@ detectionPatterns:
|
|
|
65
65
|
- id: ts-check-then-act
|
|
66
66
|
type: regex
|
|
67
67
|
language: typescript
|
|
68
|
-
pattern: "if\\s*\\(.*exists.*\\).*\\{.*create|if\\s*\\(
|
|
68
|
+
pattern: "if\\s*\\(.*exists.*\\).*\\{.*(create|write|mkdir|insert)|if\\s*\\(!.*exists.*\\).*\\{.*(create|write|mkdir|insert)"
|
|
69
69
|
confidence: medium
|
|
70
|
-
description: Detects check-then-act pattern
|
|
70
|
+
description: Detects check-then-act TOCTOU pattern (check existence then create)
|
|
71
71
|
|
|
72
72
|
- id: ts-promise-race-unsafe
|
|
73
73
|
type: regex
|
|
@@ -28,19 +28,12 @@ detectionPatterns:
|
|
|
28
28
|
confidence: medium
|
|
29
29
|
description: Detects mutable global state
|
|
30
30
|
|
|
31
|
-
- id: python-
|
|
31
|
+
- id: python-thread-no-lock
|
|
32
32
|
type: regex
|
|
33
33
|
language: python
|
|
34
|
-
pattern: "\\
|
|
35
|
-
confidence:
|
|
36
|
-
description: Detects
|
|
37
|
-
|
|
38
|
-
- id: python-no-lock
|
|
39
|
-
type: regex
|
|
40
|
-
language: python
|
|
41
|
-
pattern: "threading\\.Thread|multiprocessing\\.Process"
|
|
42
|
-
confidence: low
|
|
43
|
-
description: Detects threading (verify locking)
|
|
34
|
+
pattern: "threading\\.Thread.*(?!Lock\\(|RLock\\(|Semaphore\\()"
|
|
35
|
+
confidence: medium
|
|
36
|
+
description: Detects thread creation without visible locking in same scope
|
|
44
37
|
negativePattern: "Lock\\(|RLock\\(|Semaphore\\("
|
|
45
38
|
|
|
46
39
|
- id: python-check-then-act
|
|
@@ -50,12 +43,12 @@ detectionPatterns:
|
|
|
50
43
|
confidence: medium
|
|
51
44
|
description: Detects check-then-act pattern (TOCTOU)
|
|
52
45
|
|
|
53
|
-
- id: ts-
|
|
46
|
+
- id: ts-var-declaration
|
|
54
47
|
type: regex
|
|
55
48
|
language: typescript
|
|
56
|
-
pattern: "
|
|
57
|
-
confidence:
|
|
58
|
-
description: Detects
|
|
49
|
+
pattern: "\\bvar\\s+\\w+\\s*="
|
|
50
|
+
confidence: medium
|
|
51
|
+
description: Detects var declarations (function-scoped, potential unintended sharing)
|
|
59
52
|
|
|
60
53
|
- id: ts-async-race
|
|
61
54
|
type: regex
|
|
@@ -67,9 +60,13 @@ detectionPatterns:
|
|
|
67
60
|
- id: ts-non-atomic-update
|
|
68
61
|
type: regex
|
|
69
62
|
language: typescript
|
|
70
|
-
pattern: "
|
|
71
|
-
confidence:
|
|
72
|
-
description: Detects non-atomic increment
|
|
63
|
+
pattern: "await.*\\w+\\s*=\\s*\\w+\\s*\\+\\s*1|await.*\\w+\\+\\+|\\w+\\+\\+.*await"
|
|
64
|
+
confidence: medium
|
|
65
|
+
description: Detects non-atomic increment in async context (potential race condition)
|
|
66
|
+
sources:
|
|
67
|
+
- "\\basync\\b"
|
|
68
|
+
- "\\bawait\\b"
|
|
69
|
+
- "\\bPromise\\b"
|
|
73
70
|
|
|
74
71
|
- id: ts-database-upsert
|
|
75
72
|
type: regex
|
|
@@ -56,7 +56,7 @@ detectionPatterns:
|
|
|
56
56
|
type: regex
|
|
57
57
|
language: typescript
|
|
58
58
|
pattern: "new TextDecoder\\(\\)|TextDecoder\\(\\)"
|
|
59
|
-
confidence:
|
|
59
|
+
confidence: medium
|
|
60
60
|
description: Detects TextDecoder without explicit encoding
|
|
61
61
|
|
|
62
62
|
- id: ts-buffer-tostring-default
|
|
@@ -76,9 +76,9 @@ detectionPatterns:
|
|
|
76
76
|
- id: ts-length-emoji
|
|
77
77
|
type: regex
|
|
78
78
|
language: typescript
|
|
79
|
-
pattern: "\\.length
|
|
80
|
-
confidence:
|
|
81
|
-
description: Detects string length (
|
|
79
|
+
pattern: "\\.length\\s*[<>]=?\\s*\\d+.*\\.charAt|\\.length.*\\.charCodeAt|\\.split\\(.*\\)\\.length"
|
|
80
|
+
confidence: medium
|
|
81
|
+
description: Detects string length used with char operations (may be wrong for emoji)
|
|
82
82
|
negativePattern: "\\[\\.\\.\\.\\w+\\]\\.length|Array\\.from\\("
|
|
83
83
|
|
|
84
84
|
testTemplates:
|
|
@@ -41,12 +41,12 @@ detectionPatterns:
|
|
|
41
41
|
confidence: high
|
|
42
42
|
description: Detects arithmetic with potential None values
|
|
43
43
|
|
|
44
|
-
- id: python-json-
|
|
44
|
+
- id: python-json-no-default
|
|
45
45
|
type: regex
|
|
46
46
|
language: python
|
|
47
|
-
pattern: "json\\.loads|json\\.
|
|
48
|
-
confidence:
|
|
49
|
-
description: Detects JSON
|
|
47
|
+
pattern: "json\\.loads?\\(.*\\)\\[|json\\.loads?\\(.*\\)\\."
|
|
48
|
+
confidence: medium
|
|
49
|
+
description: Detects JSON parse result accessed without null check
|
|
50
50
|
negativePattern: "or\\s+\\{\\}|or\\s+\\[\\]|\\.get\\("
|
|
51
51
|
|
|
52
52
|
- id: ts-null-vs-undefined
|
|
@@ -56,27 +56,12 @@ detectionPatterns:
|
|
|
56
56
|
confidence: medium
|
|
57
57
|
description: Detects checking only null or undefined, not both
|
|
58
58
|
|
|
59
|
-
- id: ts-
|
|
60
|
-
type: regex
|
|
61
|
-
language: typescript
|
|
62
|
-
pattern: "\\w+\\.\\w+\\.\\w+(?!\\.?)"
|
|
63
|
-
confidence: low
|
|
64
|
-
description: Detects deep property access without optional chaining
|
|
65
|
-
negativePattern: "\\?\\."
|
|
66
|
-
|
|
67
|
-
- id: ts-nullable-db-field
|
|
59
|
+
- id: ts-json-parse-no-try
|
|
68
60
|
type: regex
|
|
69
61
|
language: typescript
|
|
70
|
-
pattern: "
|
|
71
|
-
confidence:
|
|
72
|
-
description: Detects
|
|
73
|
-
|
|
74
|
-
- id: ts-json-parse-null
|
|
75
|
-
type: regex
|
|
76
|
-
language: typescript
|
|
77
|
-
pattern: "JSON\\.parse\\s*\\("
|
|
78
|
-
confidence: low
|
|
79
|
-
description: Detects JSON parsing (verify null handling)
|
|
62
|
+
pattern: "JSON\\.parse\\s*\\((?!.*try|.*catch)"
|
|
63
|
+
confidence: medium
|
|
64
|
+
description: Detects JSON.parse without visible error handling
|
|
80
65
|
|
|
81
66
|
testTemplates:
|
|
82
67
|
- id: pytest-null-handling
|
|
@@ -21,54 +21,26 @@ references:
|
|
|
21
21
|
- https://en.wikipedia.org/wiki/Boundary_testing
|
|
22
22
|
|
|
23
23
|
detectionPatterns:
|
|
24
|
-
- id: python-
|
|
24
|
+
- id: python-unchecked-index-user-input
|
|
25
25
|
type: regex
|
|
26
26
|
language: python
|
|
27
|
-
pattern: "\\
|
|
28
|
-
confidence:
|
|
29
|
-
description: Detects array
|
|
30
|
-
|
|
31
|
-
- id: python-comparison-boundary
|
|
32
|
-
type: regex
|
|
33
|
-
language: python
|
|
34
|
-
pattern: "if\\s+\\w+\\s*[<>]=?\\s*\\d+|if\\s+\\d+\\s*[<>]=?\\s*\\w+"
|
|
35
|
-
confidence: low
|
|
36
|
-
description: Detects numeric comparisons (verify off-by-one)
|
|
37
|
-
|
|
38
|
-
- id: python-slice-operation
|
|
39
|
-
type: regex
|
|
40
|
-
language: python
|
|
41
|
-
pattern: "\\[:\\d+\\]|\\[\\d+:\\]|\\[-\\d+:\\]"
|
|
42
|
-
confidence: low
|
|
43
|
-
description: Detects slice operations (verify bounds)
|
|
44
|
-
|
|
45
|
-
- id: python-loop-range
|
|
46
|
-
type: regex
|
|
47
|
-
language: python
|
|
48
|
-
pattern: "for\\s+\\w+\\s+in\\s+range\\("
|
|
49
|
-
confidence: low
|
|
50
|
-
description: Detects range loops (verify inclusive/exclusive)
|
|
51
|
-
|
|
52
|
-
- id: ts-array-access
|
|
53
|
-
type: regex
|
|
54
|
-
language: typescript
|
|
55
|
-
pattern: "\\[\\w+\\]|\\[\\.length\\s*-\\s*1\\]"
|
|
56
|
-
confidence: low
|
|
57
|
-
description: Detects array index access
|
|
27
|
+
pattern: "\\w+\\[\\s*(request\\.|params\\.|args\\.|input)"
|
|
28
|
+
confidence: medium
|
|
29
|
+
description: Detects array indexing with user-controlled input without bounds check
|
|
58
30
|
|
|
59
|
-
- id: ts-
|
|
31
|
+
- id: ts-unchecked-index-user-input
|
|
60
32
|
type: regex
|
|
61
33
|
language: typescript
|
|
62
|
-
pattern: "
|
|
63
|
-
confidence:
|
|
64
|
-
description: Detects
|
|
34
|
+
pattern: "\\w+\\[\\s*(req\\.|params\\.|query\\.|body\\.|input)"
|
|
35
|
+
confidence: medium
|
|
36
|
+
description: Detects array indexing with user-controlled input without bounds check
|
|
65
37
|
|
|
66
|
-
- id:
|
|
38
|
+
- id: python-no-length-check-slice
|
|
67
39
|
type: regex
|
|
68
|
-
language:
|
|
69
|
-
pattern: "
|
|
40
|
+
language: python
|
|
41
|
+
pattern: "\\w+\\[.*:\\s*\\]\\s*(?!.*(?:len|if|assert))"
|
|
70
42
|
confidence: low
|
|
71
|
-
description: Detects
|
|
43
|
+
description: Detects array slicing without prior length validation that may cause unexpected empty results
|
|
72
44
|
|
|
73
45
|
testTemplates:
|
|
74
46
|
- id: pytest-boundary-testing
|
|
@@ -59,6 +59,12 @@ detectionPatterns:
|
|
|
59
59
|
pattern: "eval\\(|new Function\\(|setTimeout\\(.*\\+"
|
|
60
60
|
confidence: high
|
|
61
61
|
description: Detects dynamic code evaluation
|
|
62
|
+
sources:
|
|
63
|
+
- "req\\.(body|params|query|headers)"
|
|
64
|
+
- "\\buser[Ii]nput\\b"
|
|
65
|
+
- "searchParams\\.get\\("
|
|
66
|
+
- "\\bprocess\\.argv"
|
|
67
|
+
- "\\breadline"
|
|
62
68
|
|
|
63
69
|
- id: ts-innerhtml-input
|
|
64
70
|
type: regex
|
|
@@ -66,6 +72,19 @@ detectionPatterns:
|
|
|
66
72
|
pattern: "\\.innerHTML\\s*=|\\.outerHTML\\s*="
|
|
67
73
|
confidence: high
|
|
68
74
|
description: Detects innerHTML assignment
|
|
75
|
+
sources:
|
|
76
|
+
- "req\\.(body|params|query|headers)"
|
|
77
|
+
- "\\buser[Ii]nput\\b"
|
|
78
|
+
- "searchParams\\.get\\("
|
|
79
|
+
- "\\blocation\\.(hash|search|href)"
|
|
80
|
+
- "\\bwindow\\.location"
|
|
81
|
+
- "\\bURLSearchParams"
|
|
82
|
+
sanitizers:
|
|
83
|
+
- "DOMPurify\\.sanitize\\("
|
|
84
|
+
- "escapeHtml\\("
|
|
85
|
+
- "sanitizeHtml\\("
|
|
86
|
+
- "encodeURIComponent\\("
|
|
87
|
+
- "textContent\\s*="
|
|
69
88
|
|
|
70
89
|
- id: ts-template-injection
|
|
71
90
|
type: regex
|
|
@@ -20,54 +20,26 @@ references:
|
|
|
20
20
|
- https://cwe.mitre.org/data/definitions/457.html
|
|
21
21
|
|
|
22
22
|
detectionPatterns:
|
|
23
|
-
- id:
|
|
23
|
+
- id: ts-non-null-assertion
|
|
24
24
|
type: regex
|
|
25
|
-
language:
|
|
26
|
-
pattern: "\\w
|
|
27
|
-
confidence:
|
|
28
|
-
description: Detects
|
|
25
|
+
language: typescript
|
|
26
|
+
pattern: "\\w+!\\.|\\w+!\\["
|
|
27
|
+
confidence: high
|
|
28
|
+
description: Detects non-null assertion operator (unsafe type narrowing bypass)
|
|
29
29
|
|
|
30
|
-
- id: python-
|
|
30
|
+
- id: python-none-attribute-access
|
|
31
31
|
type: regex
|
|
32
32
|
language: python
|
|
33
|
-
pattern: "\\
|
|
33
|
+
pattern: "(?:return|=)\\s+\\w+\\.\\w+.*(?!.*(?:if|is not None|is None))"
|
|
34
34
|
confidence: medium
|
|
35
|
-
description: Detects
|
|
35
|
+
description: Detects attribute access on a variable that may be None without a prior null check
|
|
36
36
|
|
|
37
|
-
- id: python-
|
|
37
|
+
- id: python-no-default-dict-access
|
|
38
38
|
type: regex
|
|
39
39
|
language: python
|
|
40
|
-
pattern: "
|
|
41
|
-
confidence: medium
|
|
42
|
-
description: Detects Optional type without default value
|
|
43
|
-
|
|
44
|
-
- id: ts-no-null-check
|
|
45
|
-
type: regex
|
|
46
|
-
language: typescript
|
|
47
|
-
pattern: "\\w+\\.\\w+(?!.*\\?\\.|.*&&|.*\\|\\|)"
|
|
48
|
-
confidence: low
|
|
49
|
-
description: Detects property access without null check
|
|
50
|
-
|
|
51
|
-
- id: ts-undefined-equality
|
|
52
|
-
type: regex
|
|
53
|
-
language: typescript
|
|
54
|
-
pattern: "===\\s*undefined(?!.*null)|!==\\s*undefined(?!.*null)"
|
|
55
|
-
confidence: medium
|
|
56
|
-
description: Detects undefined check without null check
|
|
57
|
-
|
|
58
|
-
- id: ts-non-null-assertion
|
|
59
|
-
type: regex
|
|
60
|
-
language: typescript
|
|
61
|
-
pattern: "\\w+!\\.|\\w+!\\["
|
|
62
|
-
confidence: high
|
|
63
|
-
description: Detects non-null assertion operator
|
|
64
|
-
|
|
65
|
-
- id: ts-optional-chaining-missing
|
|
66
|
-
type: regex
|
|
67
|
-
language: typescript
|
|
68
|
-
pattern: "\\w+\\.\\w+\\.\\w+(?!\\?\\.)"
|
|
40
|
+
pattern: "\\w+\\[\\s*['\"]\\w+['\"]\\s*\\](?!.*\\.get)"
|
|
69
41
|
confidence: low
|
|
70
|
-
description: Detects
|
|
42
|
+
description: Detects direct dictionary bracket access without using .get() which raises KeyError on missing keys
|
|
71
43
|
|
|
72
44
|
testTemplates:
|
|
73
45
|
- id: pytest-null-undefined
|
|
@@ -70,9 +70,15 @@ detectionPatterns:
|
|
|
70
70
|
- id: ts-no-econnrefused
|
|
71
71
|
type: regex
|
|
72
72
|
language: typescript
|
|
73
|
-
pattern: "catch\\s*\\([^)]*\\)\\s*\\{(?!.*ECONNREFUSED|.*code)"
|
|
74
|
-
confidence:
|
|
75
|
-
description: Detects catch block not checking error codes
|
|
73
|
+
pattern: "(fetch|axios|got|request|http\\.get|https\\.get).*catch\\s*\\([^)]*\\)\\s*\\{(?!.*ECONNREFUSED|.*code|.*retry)"
|
|
74
|
+
confidence: medium
|
|
75
|
+
description: Detects network request catch block not checking error codes
|
|
76
|
+
sources:
|
|
77
|
+
- "\\bfetch\\("
|
|
78
|
+
- "\\baxios\\b"
|
|
79
|
+
- "\\bgot\\("
|
|
80
|
+
- "\\bhttp\\.get\\("
|
|
81
|
+
- "\\bhttps\\.get\\("
|
|
76
82
|
|
|
77
83
|
- id: ts-socket-no-error-event
|
|
78
84
|
type: regex
|
|
@@ -25,19 +25,12 @@ references:
|
|
|
25
25
|
- https://developer.chrome.com/docs/devtools/memory-problems/
|
|
26
26
|
|
|
27
27
|
detectionPatterns:
|
|
28
|
-
- id: python-
|
|
28
|
+
- id: python-global-list-append
|
|
29
29
|
type: regex
|
|
30
30
|
language: python
|
|
31
|
-
pattern: "\\
|
|
32
|
-
confidence:
|
|
33
|
-
description: Detects
|
|
34
|
-
|
|
35
|
-
- id: python-list-append-loop
|
|
36
|
-
type: regex
|
|
37
|
-
language: python
|
|
38
|
-
pattern: "while.*\\.append\\(|for.*\\.append\\("
|
|
39
|
-
confidence: low
|
|
40
|
-
description: Detects list growing in loop (verify bounds)
|
|
31
|
+
pattern: "^\\w+\\s*=\\s*\\[\\].*\\.append\\("
|
|
32
|
+
confidence: medium
|
|
33
|
+
description: Detects module-level list accumulation without bounds
|
|
41
34
|
|
|
42
35
|
- id: python-global-accumulator
|
|
43
36
|
type: regex
|
|
@@ -60,12 +53,12 @@ detectionPatterns:
|
|
|
60
53
|
confidence: medium
|
|
61
54
|
description: Detects potential circular references
|
|
62
55
|
|
|
63
|
-
- id: ts-
|
|
56
|
+
- id: ts-module-level-map
|
|
64
57
|
type: regex
|
|
65
58
|
language: typescript
|
|
66
|
-
pattern: "
|
|
67
|
-
confidence:
|
|
68
|
-
description: Detects
|
|
59
|
+
pattern: "^(?:export\\s+)?const\\s+\\w+\\s*=\\s*new\\s+Map\\(\\)"
|
|
60
|
+
confidence: medium
|
|
61
|
+
description: Detects module-level Map without eviction (potential memory leak in long-running servers)
|
|
69
62
|
|
|
70
63
|
- id: ts-event-listener-no-remove
|
|
71
64
|
type: regex
|
|
@@ -84,9 +77,14 @@ detectionPatterns:
|
|
|
84
77
|
- id: ts-array-push-unbounded
|
|
85
78
|
type: regex
|
|
86
79
|
language: typescript
|
|
87
|
-
pattern: "
|
|
80
|
+
pattern: "\\bmodule\\b.*\\.push\\(|\\bglobal\\b.*\\.push\\(|\\bthis\\.\\w+\\.push\\("
|
|
88
81
|
confidence: low
|
|
89
|
-
description: Detects
|
|
82
|
+
description: Detects unbounded growth on module/global/instance arrays (potential leak in long-running processes)
|
|
83
|
+
sources:
|
|
84
|
+
- "\\bsetInterval\\("
|
|
85
|
+
- "\\b\\.on\\("
|
|
86
|
+
- "\\bEventEmitter\\b"
|
|
87
|
+
- "\\bserver\\b"
|
|
90
88
|
|
|
91
89
|
testTemplates:
|
|
92
90
|
- id: pytest-memory-leak
|
|
@@ -118,6 +118,14 @@ detectionPatterns:
|
|
|
118
118
|
description: |
|
|
119
119
|
[REVIEW REQUIRED] User ID taken from request parameter.
|
|
120
120
|
Verify ownership check exists before accessing resources.
|
|
121
|
+
sources:
|
|
122
|
+
- "req\\.(body|params|query|headers)"
|
|
123
|
+
- "searchParams\\.get\\("
|
|
124
|
+
sanitizers:
|
|
125
|
+
- "req\\.user\\.id\\s*===|req\\.user\\.id\\s*=="
|
|
126
|
+
- "ownershipCheck\\(|verifyOwnership\\("
|
|
127
|
+
- "isOwner\\("
|
|
128
|
+
- "req\\.user\\.id\\s*!==.*throw|req\\.user\\.id\\s*!=.*throw"
|
|
121
129
|
|
|
122
130
|
- id: idor-direct-lookup
|
|
123
131
|
type: regex
|
|
@@ -77,6 +77,16 @@ detectionPatterns:
|
|
|
77
77
|
pattern: "child_process\\.exec\\s*\\(|exec\\s*\\(`.*\\$\\{"
|
|
78
78
|
confidence: high
|
|
79
79
|
description: Detects child_process.exec with potential user input
|
|
80
|
+
sources:
|
|
81
|
+
- "req\\.(body|params|query|headers)"
|
|
82
|
+
- "\\buser[Ii]nput\\b"
|
|
83
|
+
- "searchParams\\.get\\("
|
|
84
|
+
- "\\bprocess\\.argv"
|
|
85
|
+
sanitizers:
|
|
86
|
+
- "\\bexecFile\\("
|
|
87
|
+
- "\\bspawnSync\\(.*\\["
|
|
88
|
+
- "\\bshellEscape\\("
|
|
89
|
+
- "\\bescapeShellArg\\("
|
|
80
90
|
|
|
81
91
|
- id: ts-child-process-spawn-shell
|
|
82
92
|
type: regex
|
|
@@ -84,6 +94,13 @@ detectionPatterns:
|
|
|
84
94
|
pattern: "spawn\\s*\\(.*shell:\\s*true"
|
|
85
95
|
confidence: high
|
|
86
96
|
description: Detects spawn with shell option enabled
|
|
97
|
+
sources:
|
|
98
|
+
- "req\\.(body|params|query|headers)"
|
|
99
|
+
- "\\buser[Ii]nput\\b"
|
|
100
|
+
- "searchParams\\.get\\("
|
|
101
|
+
sanitizers:
|
|
102
|
+
- "\\bshellEscape\\("
|
|
103
|
+
- "\\bescapeShellArg\\("
|
|
87
104
|
|
|
88
105
|
- id: ts-execsync
|
|
89
106
|
type: regex
|
|
@@ -64,6 +64,16 @@ detectionPatterns:
|
|
|
64
64
|
confidence: low
|
|
65
65
|
description: Detects Express state-changing routes without csrf middleware
|
|
66
66
|
negativePattern: "csurf|csrf\\(|csrfProtection"
|
|
67
|
+
sources:
|
|
68
|
+
- "req\\.(body|params|query|headers)"
|
|
69
|
+
- "\\buser[Ii]nput\\b"
|
|
70
|
+
sanitizers:
|
|
71
|
+
- "csurf\\("
|
|
72
|
+
- "csrfProtection"
|
|
73
|
+
- "csrf\\("
|
|
74
|
+
- "SameSite=Strict|sameSite:\\s*[\"']strict[\"']"
|
|
75
|
+
- "SameSite=Lax|sameSite:\\s*[\"']lax[\"']"
|
|
76
|
+
- "lusca\\.csrf"
|
|
67
77
|
|
|
68
78
|
- id: ts-fetch-no-credentials
|
|
69
79
|
type: regex
|
|
@@ -72,6 +82,15 @@ detectionPatterns:
|
|
|
72
82
|
confidence: low
|
|
73
83
|
description: Detects fetch with state-changing methods (needs CSRF token)
|
|
74
84
|
negativePattern: "X-CSRF|csrf|_token"
|
|
85
|
+
sources:
|
|
86
|
+
- "req\\.(body|params|query|headers)"
|
|
87
|
+
- "\\buser[Ii]nput\\b"
|
|
88
|
+
sanitizers:
|
|
89
|
+
- "X-CSRF-Token"
|
|
90
|
+
- "csrf[Tt]oken"
|
|
91
|
+
- "_csrf"
|
|
92
|
+
- "SameSite=Strict|sameSite:\\s*[\"']strict[\"']"
|
|
93
|
+
- "SameSite=Lax|sameSite:\\s*[\"']lax[\"']"
|
|
75
94
|
|
|
76
95
|
- id: ts-axios-no-csrf
|
|
77
96
|
type: regex
|
|
@@ -51,6 +51,13 @@ detectionPatterns:
|
|
|
51
51
|
[REVIEW REQUIRED] API returns full user/account object.
|
|
52
52
|
Verify sensitive fields (password, SSN, etc.) are excluded.
|
|
53
53
|
negativePattern: "\\.omit\\(|\\.pick\\(|\\.select\\(|exclude|sanitize"
|
|
54
|
+
sanitizers:
|
|
55
|
+
- "\\.select\\("
|
|
56
|
+
- "\\.omit\\("
|
|
57
|
+
- "\\bpick\\("
|
|
58
|
+
- "\\bomit\\("
|
|
59
|
+
- "\\.exclude\\("
|
|
60
|
+
- "\\bsanitize(User|Response)\\("
|
|
54
61
|
|
|
55
62
|
- id: returning-full-object-py
|
|
56
63
|
type: regex
|
|
@@ -79,6 +86,11 @@ detectionPatterns:
|
|
|
79
86
|
description: |
|
|
80
87
|
[REVIEW REQUIRED] SELECT * query on user table.
|
|
81
88
|
Select only required fields to prevent data leakage.
|
|
89
|
+
sanitizers:
|
|
90
|
+
- "\\.select\\("
|
|
91
|
+
- "SELECT\\s+(id|name|email|username)"
|
|
92
|
+
- "\\.omit\\("
|
|
93
|
+
- "\\bpick\\("
|
|
82
94
|
|
|
83
95
|
# ORM without field selection
|
|
84
96
|
- id: prisma-findmany-no-select
|
|
@@ -89,6 +101,11 @@ detectionPatterns:
|
|
|
89
101
|
description: |
|
|
90
102
|
[REVIEW REQUIRED] Prisma query without select clause.
|
|
91
103
|
Returns all fields by default.
|
|
104
|
+
sanitizers:
|
|
105
|
+
- "select:"
|
|
106
|
+
- "\\.omit\\("
|
|
107
|
+
- "\\bpick\\("
|
|
108
|
+
- "exclude:"
|
|
92
109
|
|
|
93
110
|
- id: sequelize-findall-no-attributes
|
|
94
111
|
type: regex
|
|
@@ -134,6 +151,13 @@ detectionPatterns:
|
|
|
134
151
|
description: |
|
|
135
152
|
[REVIEW REQUIRED] Spreading user object in response.
|
|
136
153
|
May include sensitive fields unintentionally.
|
|
154
|
+
sanitizers:
|
|
155
|
+
- "\\.select\\("
|
|
156
|
+
- "\\.omit\\("
|
|
157
|
+
- "\\bpick\\("
|
|
158
|
+
- "\\bomit\\("
|
|
159
|
+
- "\\bexclude\\("
|
|
160
|
+
- "const\\s*\\{\\s*password.*\\}\\s*=.*user"
|
|
137
161
|
|
|
138
162
|
testTemplates:
|
|
139
163
|
- id: pytest-data-exposure-review
|
|
@@ -88,16 +88,16 @@ detectionPatterns:
|
|
|
88
88
|
- id: lodash-typosquat
|
|
89
89
|
type: regex
|
|
90
90
|
language: typescript
|
|
91
|
-
pattern: "(l0dash|lodahs|1odash|lodassh|lodsh)
|
|
91
|
+
pattern: "(import|require).*[\"'](l0dash|lodahs|1odash|lodassh|lodsh)[\"']"
|
|
92
92
|
confidence: high
|
|
93
|
-
description: Potential lodash typosquat
|
|
93
|
+
description: Potential lodash typosquat in import/require statement
|
|
94
94
|
|
|
95
95
|
- id: express-typosquat
|
|
96
96
|
type: regex
|
|
97
97
|
language: typescript
|
|
98
|
-
pattern: "(expres
|
|
98
|
+
pattern: "(import|require).*[\"'](expres|expresss|3xpress)[\"']"
|
|
99
99
|
confidence: high
|
|
100
|
-
description: Potential express typosquat
|
|
100
|
+
description: Potential express typosquat in import/require statement
|
|
101
101
|
|
|
102
102
|
- id: requests-typosquat
|
|
103
103
|
type: regex
|
|
@@ -130,7 +130,7 @@ detectionPatterns:
|
|
|
130
130
|
- id: shai-hulud-packages
|
|
131
131
|
type: regex
|
|
132
132
|
language: typescript
|
|
133
|
-
pattern: "[\"'`](ngx-bootstrap|ng2-file-upload|@ctrl/tinycolor
|
|
133
|
+
pattern: "(import|require|from).*[\"'`](ngx-bootstrap|ng2-file-upload|@ctrl/tinycolor)[\"'`]"
|
|
134
134
|
confidence: high
|
|
135
135
|
description: |
|
|
136
136
|
CRITICAL: Package affected by Shai-Hulud supply chain attack (Sep 2025).
|
|
@@ -139,7 +139,7 @@ detectionPatterns:
|
|
|
139
139
|
- id: compromised-packages-wave2
|
|
140
140
|
type: regex
|
|
141
141
|
language: typescript
|
|
142
|
-
pattern: "[\"'`](@acitons/artifact|huggingface-cli|react-dom-utils-helper)[\"'`]"
|
|
142
|
+
pattern: "(import|require|from).*[\"'`](@acitons/artifact|huggingface-cli|react-dom-utils-helper)[\"'`]"
|
|
143
143
|
confidence: high
|
|
144
144
|
description: |
|
|
145
145
|
CRITICAL: Known malicious/typosquatted package.
|