pinata-security-cli 0.6.0 → 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/dist/cli/index.js +1527 -369
- 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 +5 -1
- package/src/categories/definitions/data/data-race.yml +6 -2
- package/src/categories/definitions/input/boundary-testing.yml +7 -0
- package/src/categories/definitions/input/injection-fuzzing.yml +19 -0
- package/src/categories/definitions/input/null-undefined.yml +14 -0
- package/src/categories/definitions/network/connection-failure.yml +8 -2
- package/src/categories/definitions/resource/memory-leak.yml +7 -2
- 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.6.
|
|
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",
|
|
@@ -78,17 +78,21 @@
|
|
|
78
78
|
"@stryker-mutator/core": "^9.5.1",
|
|
79
79
|
"@stryker-mutator/typescript-checker": "^9.5.1",
|
|
80
80
|
"@stryker-mutator/vitest-runner": "^9.5.1",
|
|
81
|
+
"@types/express": "^5.0.6",
|
|
81
82
|
"@types/js-yaml": "^4.0.9",
|
|
82
83
|
"@types/minimatch": "^5.1.2",
|
|
83
84
|
"@types/node": "^20.14.10",
|
|
85
|
+
"@types/supertest": "^7.2.0",
|
|
84
86
|
"@typescript-eslint/eslint-plugin": "^7.16.0",
|
|
85
87
|
"@typescript-eslint/parser": "^7.16.0",
|
|
86
88
|
"@vitest/coverage-v8": "^4.0.18",
|
|
87
89
|
"eslint": "^8.57.1",
|
|
88
90
|
"eslint-config-prettier": "^9.1.0",
|
|
89
91
|
"eslint-plugin-import": "^2.29.1",
|
|
92
|
+
"express": "^5.2.1",
|
|
90
93
|
"fast-check": "^4.5.3",
|
|
91
94
|
"prettier": "^3.3.3",
|
|
95
|
+
"supertest": "^7.2.2",
|
|
92
96
|
"tsup": "^8.1.0",
|
|
93
97
|
"tsx": "^4.21.0",
|
|
94
98
|
"typescript": "^5.5.3",
|
|
@@ -60,9 +60,13 @@ detectionPatterns:
|
|
|
60
60
|
- id: ts-non-atomic-update
|
|
61
61
|
type: regex
|
|
62
62
|
language: typescript
|
|
63
|
-
pattern: "
|
|
63
|
+
pattern: "await.*\\w+\\s*=\\s*\\w+\\s*\\+\\s*1|await.*\\w+\\+\\+|\\w+\\+\\+.*await"
|
|
64
64
|
confidence: medium
|
|
65
|
-
description: Detects non-atomic increment
|
|
65
|
+
description: Detects non-atomic increment in async context (potential race condition)
|
|
66
|
+
sources:
|
|
67
|
+
- "\\basync\\b"
|
|
68
|
+
- "\\bawait\\b"
|
|
69
|
+
- "\\bPromise\\b"
|
|
66
70
|
|
|
67
71
|
- id: ts-database-upsert
|
|
68
72
|
type: regex
|
|
@@ -35,6 +35,13 @@ detectionPatterns:
|
|
|
35
35
|
confidence: medium
|
|
36
36
|
description: Detects array indexing with user-controlled input without bounds check
|
|
37
37
|
|
|
38
|
+
- id: python-no-length-check-slice
|
|
39
|
+
type: regex
|
|
40
|
+
language: python
|
|
41
|
+
pattern: "\\w+\\[.*:\\s*\\]\\s*(?!.*(?:len|if|assert))"
|
|
42
|
+
confidence: low
|
|
43
|
+
description: Detects array slicing without prior length validation that may cause unexpected empty results
|
|
44
|
+
|
|
38
45
|
testTemplates:
|
|
39
46
|
- id: pytest-boundary-testing
|
|
40
47
|
language: python
|
|
@@ -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
|
|
@@ -27,6 +27,20 @@ detectionPatterns:
|
|
|
27
27
|
confidence: high
|
|
28
28
|
description: Detects non-null assertion operator (unsafe type narrowing bypass)
|
|
29
29
|
|
|
30
|
+
- id: python-none-attribute-access
|
|
31
|
+
type: regex
|
|
32
|
+
language: python
|
|
33
|
+
pattern: "(?:return|=)\\s+\\w+\\.\\w+.*(?!.*(?:if|is not None|is None))"
|
|
34
|
+
confidence: medium
|
|
35
|
+
description: Detects attribute access on a variable that may be None without a prior null check
|
|
36
|
+
|
|
37
|
+
- id: python-no-default-dict-access
|
|
38
|
+
type: regex
|
|
39
|
+
language: python
|
|
40
|
+
pattern: "\\w+\\[\\s*['\"]\\w+['\"]\\s*\\](?!.*\\.get)"
|
|
41
|
+
confidence: low
|
|
42
|
+
description: Detects direct dictionary bracket access without using .get() which raises KeyError on missing keys
|
|
43
|
+
|
|
30
44
|
testTemplates:
|
|
31
45
|
- id: pytest-null-undefined
|
|
32
46
|
language: python
|
|
@@ -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)"
|
|
73
|
+
pattern: "(fetch|axios|got|request|http\\.get|https\\.get).*catch\\s*\\([^)]*\\)\\s*\\{(?!.*ECONNREFUSED|.*code|.*retry)"
|
|
74
74
|
confidence: medium
|
|
75
|
-
description: Detects catch block not checking error codes
|
|
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
|
|
@@ -77,9 +77,14 @@ detectionPatterns:
|
|
|
77
77
|
- id: ts-array-push-unbounded
|
|
78
78
|
type: regex
|
|
79
79
|
language: typescript
|
|
80
|
-
pattern: "
|
|
80
|
+
pattern: "\\bmodule\\b.*\\.push\\(|\\bglobal\\b.*\\.push\\(|\\bthis\\.\\w+\\.push\\("
|
|
81
81
|
confidence: low
|
|
82
|
-
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"
|
|
83
88
|
|
|
84
89
|
testTemplates:
|
|
85
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.
|
|
@@ -84,6 +84,18 @@ detectionPatterns:
|
|
|
84
84
|
pattern: "serialize-javascript|js-yaml\\.load\\("
|
|
85
85
|
confidence: medium
|
|
86
86
|
description: Detects serialization libraries that may allow code execution
|
|
87
|
+
sources:
|
|
88
|
+
- "req\\.(body|params|query|headers)"
|
|
89
|
+
- "\\buser[Ii]nput\\b"
|
|
90
|
+
- "searchParams\\.get\\("
|
|
91
|
+
- "\\bprocess\\.argv"
|
|
92
|
+
sanitizers:
|
|
93
|
+
- "JSON\\.parse\\("
|
|
94
|
+
- "\\bz\\.(object|string|number|array)\\("
|
|
95
|
+
- "zod\\."
|
|
96
|
+
- "joi\\.validate\\("
|
|
97
|
+
- "Joi\\.(object|string)\\("
|
|
98
|
+
- "yaml\\.load\\(.*schema:\\s*yaml\\.JSON_SCHEMA"
|
|
87
99
|
|
|
88
100
|
- id: ts-eval-json
|
|
89
101
|
type: regex
|
|
@@ -91,6 +103,16 @@ detectionPatterns:
|
|
|
91
103
|
pattern: "eval\\s*\\(.*JSON|Function\\s*\\([\"']return[\"']\\s*\\+"
|
|
92
104
|
confidence: high
|
|
93
105
|
description: Detects eval-based JSON parsing which allows code execution
|
|
106
|
+
sources:
|
|
107
|
+
- "req\\.(body|params|query|headers)"
|
|
108
|
+
- "\\buser[Ii]nput\\b"
|
|
109
|
+
- "searchParams\\.get\\("
|
|
110
|
+
sanitizers:
|
|
111
|
+
- "JSON\\.parse\\("
|
|
112
|
+
- "\\bz\\.(object|string|number|array)\\("
|
|
113
|
+
- "zod\\."
|
|
114
|
+
- "joi\\.validate\\("
|
|
115
|
+
- "Joi\\.(object|string)\\("
|
|
94
116
|
|
|
95
117
|
- id: ts-node-serialize
|
|
96
118
|
type: regex
|
|
@@ -98,6 +120,16 @@ detectionPatterns:
|
|
|
98
120
|
pattern: "node-serialize|serialize-to-js"
|
|
99
121
|
confidence: high
|
|
100
122
|
description: Detects node-serialize which is vulnerable to RCE
|
|
123
|
+
sources:
|
|
124
|
+
- "req\\.(body|params|query|headers)"
|
|
125
|
+
- "\\buser[Ii]nput\\b"
|
|
126
|
+
- "searchParams\\.get\\("
|
|
127
|
+
sanitizers:
|
|
128
|
+
- "JSON\\.parse\\("
|
|
129
|
+
- "\\bz\\.(object|string|number|array)\\("
|
|
130
|
+
- "zod\\."
|
|
131
|
+
- "joi\\.validate\\("
|
|
132
|
+
- "Joi\\.(object|string)\\("
|
|
101
133
|
|
|
102
134
|
- id: ts-vm-runinnewcontext
|
|
103
135
|
type: regex
|
|
@@ -105,6 +137,18 @@ detectionPatterns:
|
|
|
105
137
|
pattern: "vm\\.runInNewContext\\s*\\(|vm\\.runInThisContext\\s*\\("
|
|
106
138
|
confidence: high
|
|
107
139
|
description: Detects Node.js vm module with potential untrusted code
|
|
140
|
+
sources:
|
|
141
|
+
- "req\\.(body|params|query|headers)"
|
|
142
|
+
- "\\buser[Ii]nput\\b"
|
|
143
|
+
- "searchParams\\.get\\("
|
|
144
|
+
- "\\bprocess\\.argv"
|
|
145
|
+
sanitizers:
|
|
146
|
+
- "JSON\\.parse\\("
|
|
147
|
+
- "\\bz\\.(object|string|number|array)\\("
|
|
148
|
+
- "zod\\."
|
|
149
|
+
- "joi\\.validate\\("
|
|
150
|
+
- "Joi\\.(object|string)\\("
|
|
151
|
+
- "vm2|isolated-vm"
|
|
108
152
|
|
|
109
153
|
- id: ts-unserialize
|
|
110
154
|
type: regex
|
|
@@ -46,6 +46,16 @@ detectionPatterns:
|
|
|
46
46
|
pattern: "multer\\s*\\(\\s*\\{(?!.*fileFilter)"
|
|
47
47
|
confidence: high
|
|
48
48
|
description: Multer configured without fileFilter - accepts any file type
|
|
49
|
+
sources:
|
|
50
|
+
- "req\\.file"
|
|
51
|
+
- "req\\.files"
|
|
52
|
+
- "req\\.(body|params|query)"
|
|
53
|
+
sanitizers:
|
|
54
|
+
- "fileFilter"
|
|
55
|
+
- "mimetype"
|
|
56
|
+
- "file\\.mimetype"
|
|
57
|
+
- "path\\.extname\\("
|
|
58
|
+
- "path\\.basename\\("
|
|
49
59
|
|
|
50
60
|
- id: multer-no-limits
|
|
51
61
|
type: regex
|
|
@@ -122,6 +132,16 @@ detectionPatterns:
|
|
|
122
132
|
description: |
|
|
123
133
|
[REVIEW] File processed without extension validation.
|
|
124
134
|
Verify allowed file types are checked.
|
|
135
|
+
sources:
|
|
136
|
+
- "req\\.file"
|
|
137
|
+
- "req\\.files"
|
|
138
|
+
sanitizers:
|
|
139
|
+
- "path\\.extname\\("
|
|
140
|
+
- "\\.endsWith\\("
|
|
141
|
+
- "\\.match\\("
|
|
142
|
+
- "fileFilter"
|
|
143
|
+
- "allowedExtensions"
|
|
144
|
+
- "path\\.basename\\("
|
|
125
145
|
|
|
126
146
|
- id: no-mimetype-check
|
|
127
147
|
type: regex
|
|
@@ -131,6 +151,16 @@ detectionPatterns:
|
|
|
131
151
|
description: |
|
|
132
152
|
[REVIEW] File processed without MIME type check.
|
|
133
153
|
Content-type can be spoofed, combine with magic number check.
|
|
154
|
+
sources:
|
|
155
|
+
- "req\\.file"
|
|
156
|
+
- "req\\.files"
|
|
157
|
+
sanitizers:
|
|
158
|
+
- "mimetype"
|
|
159
|
+
- "content-type"
|
|
160
|
+
- "file-type"
|
|
161
|
+
- "magic-bytes"
|
|
162
|
+
- "fileFilter"
|
|
163
|
+
- "path\\.basename\\("
|
|
134
164
|
|
|
135
165
|
# Path traversal in filename
|
|
136
166
|
- id: path-traversal-filename
|
|
@@ -141,6 +171,15 @@ detectionPatterns:
|
|
|
141
171
|
description: |
|
|
142
172
|
Filename from request used in path.join without sanitization.
|
|
143
173
|
Path traversal attack possible (../../etc/passwd).
|
|
174
|
+
sources:
|
|
175
|
+
- "req\\.file\\.originalname"
|
|
176
|
+
- "req\\.file\\.filename"
|
|
177
|
+
- "req\\.(body|params|query)"
|
|
178
|
+
sanitizers:
|
|
179
|
+
- "path\\.basename\\("
|
|
180
|
+
- "sanitizeFilename\\("
|
|
181
|
+
- "secure_filename\\("
|
|
182
|
+
- "\\.\\..*reject|\\.\\..*throw"
|
|
144
183
|
|
|
145
184
|
testTemplates:
|
|
146
185
|
- id: pytest-file-upload
|
|
@@ -77,6 +77,14 @@ detectionPatterns:
|
|
|
77
77
|
pattern: "ldap.*client\\.search\\(.*\\+|ldapClient\\.search.*`.*\\$\\{"
|
|
78
78
|
confidence: high
|
|
79
79
|
description: Detects ldapjs search with string interpolation
|
|
80
|
+
sources:
|
|
81
|
+
- "req\\.(body|params|query|headers)"
|
|
82
|
+
- "\\buser[Ii]nput\\b"
|
|
83
|
+
- "searchParams\\.get\\("
|
|
84
|
+
sanitizers:
|
|
85
|
+
- "ldap\\.escape\\("
|
|
86
|
+
- "escapeLdap\\("
|
|
87
|
+
- "sanitizeFilter\\("
|
|
80
88
|
|
|
81
89
|
- id: ts-ldap-filter-template
|
|
82
90
|
type: regex
|
|
@@ -84,6 +92,12 @@ detectionPatterns:
|
|
|
84
92
|
pattern: "ldap.*filter.*=.*`.*\\$\\{|ldapFilter.*\\$\\{"
|
|
85
93
|
confidence: high
|
|
86
94
|
description: Detects LDAP filter with template literal interpolation
|
|
95
|
+
sources:
|
|
96
|
+
- "req\\.(body|params|query|headers)"
|
|
97
|
+
- "\\buser[Ii]nput\\b"
|
|
98
|
+
sanitizers:
|
|
99
|
+
- "ldap\\.escape\\("
|
|
100
|
+
- "escapeLdap\\("
|
|
87
101
|
|
|
88
102
|
- id: ts-activedirectory
|
|
89
103
|
type: regex
|
|
@@ -91,6 +105,12 @@ detectionPatterns:
|
|
|
91
105
|
pattern: "activedirectory.*find.*\\+|ad\\.find.*`.*\\$\\{"
|
|
92
106
|
confidence: medium
|
|
93
107
|
description: Detects ActiveDirectory library with user input
|
|
108
|
+
sources:
|
|
109
|
+
- "req\\.(body|params|query|headers)"
|
|
110
|
+
- "\\buser[Ii]nput\\b"
|
|
111
|
+
sanitizers:
|
|
112
|
+
- "ldap\\.escape\\("
|
|
113
|
+
- "escapeLdap\\("
|
|
94
114
|
|
|
95
115
|
- id: ts-ldap-escape-missing
|
|
96
116
|
type: regex
|
|
@@ -99,6 +119,9 @@ detectionPatterns:
|
|
|
99
119
|
confidence: medium
|
|
100
120
|
description: Detects LDAP search operations
|
|
101
121
|
negativePattern: "ldap\\.escape|escape.*filter|sanitize"
|
|
122
|
+
sources:
|
|
123
|
+
- "req\\.(body|params|query|headers)"
|
|
124
|
+
- "\\buser[Ii]nput\\b"
|
|
102
125
|
|
|
103
126
|
testTemplates:
|
|
104
127
|
- id: pytest-ldap-injection
|
|
@@ -80,12 +80,25 @@ detectionPatterns:
|
|
|
80
80
|
pattern: "fs\\.(readFile|readFileSync|createReadStream)\\s*\\(.*\\+|fs\\.(readFile|readFileSync)\\s*\\(`.*\\$\\{"
|
|
81
81
|
confidence: high
|
|
82
82
|
description: Detects fs.readFile with string concatenation or template literal
|
|
83
|
+
sources:
|
|
84
|
+
- "req\\.(body|params|query|headers)"
|
|
85
|
+
- "\\buser[Ii]nput\\b"
|
|
86
|
+
- "searchParams\\.get\\("
|
|
87
|
+
sanitizers:
|
|
88
|
+
- "path\\.resolve\\(.*path\\.normalize"
|
|
89
|
+
- "\\.startsWith\\("
|
|
90
|
+
- "path\\.relative\\(.*\\.startsWith"
|
|
91
|
+
- "\\brealpath"
|
|
83
92
|
|
|
84
93
|
- id: ts-path-join-req
|
|
85
94
|
type: regex
|
|
86
95
|
language: typescript
|
|
87
96
|
pattern: "path\\.join\\s*\\(.*req\\.(params|query|body)"
|
|
88
97
|
confidence: medium
|
|
98
|
+
sanitizers:
|
|
99
|
+
- "\\.startsWith\\("
|
|
100
|
+
- "path\\.relative\\(.*\\.startsWith"
|
|
101
|
+
- "\\brealpath"
|
|
89
102
|
description: Detects path.join with request parameters
|
|
90
103
|
negativePattern: "path\\.resolve.*includes\\(|\\.\\.\\/'"
|
|
91
104
|
|
|
@@ -44,6 +44,14 @@ detectionPatterns:
|
|
|
44
44
|
description: |
|
|
45
45
|
CRITICAL: User input concatenated into AI prompt.
|
|
46
46
|
Attacker can inject instructions to manipulate AI behavior.
|
|
47
|
+
sources:
|
|
48
|
+
- "req\\.(body|params|query|headers)"
|
|
49
|
+
- "\\buser[Ii]nput\\b"
|
|
50
|
+
- "searchParams\\.get\\("
|
|
51
|
+
sanitizers:
|
|
52
|
+
- "sanitizePrompt\\("
|
|
53
|
+
- "stripInstructions\\("
|
|
54
|
+
- "encodeForPrompt\\("
|
|
47
55
|
|
|
48
56
|
- id: prompt-user-input-template
|
|
49
57
|
type: regex
|
|
@@ -53,6 +61,12 @@ detectionPatterns:
|
|
|
53
61
|
description: |
|
|
54
62
|
CRITICAL: User input interpolated into prompt template.
|
|
55
63
|
Use parameterized prompts or sanitize input.
|
|
64
|
+
sources:
|
|
65
|
+
- "req\\.(body|params|query|headers)"
|
|
66
|
+
- "\\buser[Ii]nput\\b"
|
|
67
|
+
sanitizers:
|
|
68
|
+
- "sanitizePrompt\\("
|
|
69
|
+
- "stripInstructions\\("
|
|
56
70
|
|
|
57
71
|
- id: python-prompt-fstring
|
|
58
72
|
type: regex
|
|
@@ -88,6 +88,16 @@ detectionPatterns:
|
|
|
88
88
|
pattern: "(query|execute|run)\\s*\\(\\s*`.*\\$\\{"
|
|
89
89
|
confidence: high
|
|
90
90
|
description: Detects database query with template literal interpolation
|
|
91
|
+
sources:
|
|
92
|
+
- "req\\.(body|params|query|headers)"
|
|
93
|
+
- "\\buser[Ii]nput\\b"
|
|
94
|
+
- "searchParams\\.get\\("
|
|
95
|
+
- "\\bargs\\b"
|
|
96
|
+
sanitizers:
|
|
97
|
+
- "\\$queryRaw\\s*`"
|
|
98
|
+
- "\\bescapeSql\\("
|
|
99
|
+
- "\\bsqlstring\\.escape\\("
|
|
100
|
+
- "\\bpg\\.escapeLiteral\\("
|
|
91
101
|
|
|
92
102
|
- id: ts-concat-query
|
|
93
103
|
type: regex
|
|
@@ -95,6 +105,16 @@ detectionPatterns:
|
|
|
95
105
|
pattern: "(query|execute|run)\\s*\\(.*\\s*\\+\\s*"
|
|
96
106
|
confidence: medium
|
|
97
107
|
description: Detects database query with string concatenation
|
|
108
|
+
sources:
|
|
109
|
+
- "req\\.(body|params|query|headers)"
|
|
110
|
+
- "\\buser[Ii]nput\\b"
|
|
111
|
+
- "searchParams\\.get\\("
|
|
112
|
+
sanitizers:
|
|
113
|
+
- "\\bescapeSql\\("
|
|
114
|
+
- "\\bsqlstring\\.escape\\("
|
|
115
|
+
- "\\bpg\\.escapeLiteral\\("
|
|
116
|
+
- "parseInt\\("
|
|
117
|
+
- "Number\\("
|
|
98
118
|
|
|
99
119
|
- id: ts-prisma-raw-unsafe
|
|
100
120
|
type: regex
|
|
@@ -102,6 +122,13 @@ detectionPatterns:
|
|
|
102
122
|
pattern: "\\$queryRawUnsafe\\s*\\(|\\$executeRawUnsafe\\s*\\("
|
|
103
123
|
confidence: high
|
|
104
124
|
description: Detects Prisma unsafe raw query methods
|
|
125
|
+
sources:
|
|
126
|
+
- "req\\.(body|params|query|headers)"
|
|
127
|
+
- "\\buser[Ii]nput\\b"
|
|
128
|
+
- "searchParams\\.get\\("
|
|
129
|
+
sanitizers:
|
|
130
|
+
- "\\$queryRaw\\s*`"
|
|
131
|
+
- "\\$executeRaw\\s*`"
|
|
105
132
|
|
|
106
133
|
- id: ts-sequelize-literal
|
|
107
134
|
type: regex
|
|
@@ -109,6 +136,9 @@ detectionPatterns:
|
|
|
109
136
|
pattern: "sequelize\\.literal\\s*\\(\\s*`.*\\$\\{"
|
|
110
137
|
confidence: high
|
|
111
138
|
description: Detects Sequelize literal with interpolation
|
|
139
|
+
sources:
|
|
140
|
+
- "req\\.(body|params|query|headers)"
|
|
141
|
+
- "\\buser[Ii]nput\\b"
|
|
112
142
|
|
|
113
143
|
# Generic template literal SQL patterns
|
|
114
144
|
- id: ts-template-sql-select
|