agent-security-scanner-mcp 3.7.0 → 3.9.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/README.md +156 -10
- package/analyzer.py +22 -5
- package/cross_file_analyzer.py +216 -0
- package/daemon.py +179 -0
- package/index.js +279 -3
- package/package.json +19 -5
- package/packages/npm-bloom.json +1 -0
- package/pattern_matcher.py +1 -0
- package/regex_fallback.py +199 -1
- package/requirements.txt +1 -0
- package/rules/prompt-injection.security.yaml +273 -41
- package/scripts/postinstall.js +60 -0
- package/skills/openclaw/SKILL.md +102 -0
- package/skills/security-review.md +139 -0
- package/skills/security-scan-batch.md +107 -0
- package/skills/security-scanner.md +76 -0
- package/src/cli/doctor.js +29 -1
- package/src/cli/init.js +93 -0
- package/src/cli/report.js +444 -0
- package/src/config.js +247 -0
- package/src/context.js +289 -0
- package/src/daemon-client.js +233 -0
- package/src/dedup.js +129 -0
- package/src/fix-patterns.js +76 -19
- package/src/history.js +159 -0
- package/src/tools/check-package.js +36 -12
- package/src/tools/fix-security.js +32 -5
- package/src/tools/import-resolver.js +249 -0
- package/src/tools/project-context.js +365 -0
- package/src/tools/scan-action.js +489 -0
- package/src/tools/scan-mcp.js +922 -0
- package/src/tools/scan-project.js +16 -4
- package/src/tools/scan-prompt.js +292 -527
- package/src/tools/scan-security.js +37 -6
- package/src/typosquat.js +210 -0
- package/src/utils.js +215 -8
- package/templates/gitlab-ci-security.yml +225 -0
- package/templates/pre-commit-hook.sh +233 -0
- package/src/tools/garak-bridge.js +0 -209
package/pattern_matcher.py
CHANGED
package/regex_fallback.py
CHANGED
|
@@ -9,10 +9,207 @@ from typing import List, Dict, Optional
|
|
|
9
9
|
import re
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
# Severity classification by vulnerability class
|
|
13
|
+
SEVERITY_MAP = {
|
|
14
|
+
# ERROR - exploitable vulnerabilities (injection, RCE, deserialization)
|
|
15
|
+
'sql-injection': 'error',
|
|
16
|
+
'sql-injection-query': 'error',
|
|
17
|
+
'sql-injection-sprintf': 'error',
|
|
18
|
+
'sql-injection-where': 'error',
|
|
19
|
+
'sql-injection-order': 'error',
|
|
20
|
+
'sql-injection-raw': 'error',
|
|
21
|
+
'sql-injection-db-cursor': 'error',
|
|
22
|
+
'sql-injection-using-sqlalchemy': 'error',
|
|
23
|
+
'sql-injection-sqlcommand': 'error',
|
|
24
|
+
'sql-injection-sqlquery': 'error',
|
|
25
|
+
'sql-injection-concat': 'error',
|
|
26
|
+
'command-injection': 'error',
|
|
27
|
+
'command-injection-exec': 'error',
|
|
28
|
+
'command-injection-system': 'error',
|
|
29
|
+
'command-injection-open': 'error',
|
|
30
|
+
'command-injection-process-start': 'error',
|
|
31
|
+
'child-process-exec': 'error',
|
|
32
|
+
'spawn-shell': 'error',
|
|
33
|
+
'dangerous-subprocess-use': 'error',
|
|
34
|
+
'dangerous-system-call': 'error',
|
|
35
|
+
'eval-detected': 'error',
|
|
36
|
+
'eval-usage': 'error',
|
|
37
|
+
'exec-detected': 'error',
|
|
38
|
+
'pickle-load': 'error',
|
|
39
|
+
'unsafe-unserialize': 'error',
|
|
40
|
+
'unsafe-yaml-load': 'error',
|
|
41
|
+
'unsafe-marshal': 'error',
|
|
42
|
+
'yaml-load': 'error',
|
|
43
|
+
'file-inclusion': 'error',
|
|
44
|
+
'path-traversal': 'error',
|
|
45
|
+
'xss-echo': 'error',
|
|
46
|
+
'xss-raw': 'error',
|
|
47
|
+
'ssrf': 'error',
|
|
48
|
+
'open-redirect': 'error',
|
|
49
|
+
'backticks-exec': 'error',
|
|
50
|
+
'preg-code-exec': 'error',
|
|
51
|
+
'assert-usage': 'error',
|
|
52
|
+
'insecure-deserialization-binaryformatter': 'error',
|
|
53
|
+
'insecure-deserialization-xmlserializer': 'error',
|
|
54
|
+
'libc-system-call': 'error',
|
|
55
|
+
'format-string-printf': 'error',
|
|
56
|
+
'format-string-syslog': 'error',
|
|
57
|
+
'xss-innerhtml': 'error',
|
|
58
|
+
'xss-response-write': 'error',
|
|
59
|
+
'path-traversal-directory-delete': 'error',
|
|
60
|
+
'path-traversal-file-delete': 'error',
|
|
61
|
+
'path-traversal-file-read': 'error',
|
|
62
|
+
|
|
63
|
+
# WARNING - risky patterns requiring attention
|
|
64
|
+
'innerHTML': 'warning',
|
|
65
|
+
'outerHTML': 'warning',
|
|
66
|
+
'document-write': 'warning',
|
|
67
|
+
'insertAdjacentHTML': 'warning',
|
|
68
|
+
'dangerouslySetInnerHTML': 'warning',
|
|
69
|
+
'function-constructor': 'warning',
|
|
70
|
+
'setTimeout-string': 'warning',
|
|
71
|
+
'strcpy-usage': 'warning',
|
|
72
|
+
'strcat-usage': 'warning',
|
|
73
|
+
'sprintf-usage': 'warning',
|
|
74
|
+
'vsprintf-usage': 'warning',
|
|
75
|
+
'gets-usage': 'warning',
|
|
76
|
+
'system-usage': 'warning',
|
|
77
|
+
'popen-usage': 'warning',
|
|
78
|
+
'hardcoded-password': 'warning',
|
|
79
|
+
'hardcoded-secret': 'warning',
|
|
80
|
+
'hardcoded-api-key': 'warning',
|
|
81
|
+
'hardcoded-connection-string': 'warning',
|
|
82
|
+
'session-secret-hardcoded': 'warning',
|
|
83
|
+
'ssl-verify-disabled': 'warning',
|
|
84
|
+
'curl-ssl-disabled': 'warning',
|
|
85
|
+
'csrf-disabled': 'warning',
|
|
86
|
+
'mass-assignment-permit-all': 'warning',
|
|
87
|
+
'constantize': 'warning',
|
|
88
|
+
'render-inline': 'warning',
|
|
89
|
+
'privileged-container': 'warning',
|
|
90
|
+
'run-as-root': 'warning',
|
|
91
|
+
'allow-privilege-escalation': 'warning',
|
|
92
|
+
'host-network': 'warning',
|
|
93
|
+
'host-pid': 'warning',
|
|
94
|
+
'host-path': 'warning',
|
|
95
|
+
'secrets-in-env': 'warning',
|
|
96
|
+
'cluster-admin-binding': 'warning',
|
|
97
|
+
'capabilities-add': 'warning',
|
|
98
|
+
'no-readonly-root': 'warning',
|
|
99
|
+
'wildcard-rbac': 'warning',
|
|
100
|
+
's3-public-read': 'warning',
|
|
101
|
+
'security-group-open-ingress': 'warning',
|
|
102
|
+
'rds-public-access': 'warning',
|
|
103
|
+
'rds-encryption-disabled': 'warning',
|
|
104
|
+
'rds-deletion-protection': 'warning',
|
|
105
|
+
'cloudtrail-disabled': 'warning',
|
|
106
|
+
'kms-key-rotation': 'warning',
|
|
107
|
+
'ebs-encryption-disabled': 'warning',
|
|
108
|
+
'ec2-imdsv1': 'warning',
|
|
109
|
+
'phpinfo-exposure': 'warning',
|
|
110
|
+
'error-display': 'warning',
|
|
111
|
+
'permissive-cors': 'warning',
|
|
112
|
+
'mcrypt-deprecated': 'warning',
|
|
113
|
+
'aws-access-key-id': 'warning',
|
|
114
|
+
'aws-secret-access-key': 'warning',
|
|
115
|
+
'github-pat': 'warning',
|
|
116
|
+
'stripe-api-key': 'warning',
|
|
117
|
+
'private-key-rsa': 'warning',
|
|
118
|
+
'database-url': 'warning',
|
|
119
|
+
'jwt-token': 'warning',
|
|
120
|
+
'openai-api-key': 'warning',
|
|
121
|
+
'python.lang.security.audit.hardcoded-password': 'warning',
|
|
122
|
+
'python.lang.security.audit.hardcoded-api-key': 'warning',
|
|
123
|
+
'generic.secrets.security.hardcoded-password': 'warning',
|
|
124
|
+
'generic.secrets.security.hardcoded-api-key': 'warning',
|
|
125
|
+
|
|
126
|
+
# INFO - informational / hygiene / low-risk patterns
|
|
127
|
+
'weak-hash-md5': 'info',
|
|
128
|
+
'weak-hash-sha1': 'info',
|
|
129
|
+
'weak-hash': 'info',
|
|
130
|
+
'weak-cipher': 'info',
|
|
131
|
+
'weak-cipher-des': 'info',
|
|
132
|
+
'ecb-mode': 'info',
|
|
133
|
+
'weak-random': 'info',
|
|
134
|
+
'insecure-random': 'info',
|
|
135
|
+
'insecure-hash-md5': 'info',
|
|
136
|
+
'insecure-hash-sha1': 'info',
|
|
137
|
+
'insecure-memset': 'info',
|
|
138
|
+
'strtok-usage': 'info',
|
|
139
|
+
'insecure-tempfile': 'info',
|
|
140
|
+
'unchecked-return': 'info',
|
|
141
|
+
'unsafe-block': 'info',
|
|
142
|
+
'unwrap-usage': 'info',
|
|
143
|
+
'raw-pointer-deref': 'info',
|
|
144
|
+
'panic-usage': 'info',
|
|
145
|
+
'compile-detected': 'info',
|
|
146
|
+
'scanf-usage': 'info',
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
# Confidence classification by rule ID
|
|
150
|
+
CONFIDENCE_MAP = {
|
|
151
|
+
# HIGH - very specific patterns, low false-positive rate
|
|
152
|
+
'sql-injection-db-cursor': 'HIGH',
|
|
153
|
+
'sql-injection-using-sqlalchemy': 'HIGH',
|
|
154
|
+
'sql-injection-sqlcommand': 'HIGH',
|
|
155
|
+
'sql-injection-sqlquery': 'HIGH',
|
|
156
|
+
'sql-injection-concat': 'HIGH',
|
|
157
|
+
'format-string-printf': 'HIGH',
|
|
158
|
+
'format-string-syslog': 'HIGH',
|
|
159
|
+
'pickle-load': 'HIGH',
|
|
160
|
+
'eval-detected': 'HIGH',
|
|
161
|
+
'eval-usage': 'HIGH',
|
|
162
|
+
'exec-detected': 'HIGH',
|
|
163
|
+
'child-process-exec': 'HIGH',
|
|
164
|
+
'dangerous-subprocess-use': 'HIGH',
|
|
165
|
+
'dangerous-system-call': 'HIGH',
|
|
166
|
+
'hardcoded-password': 'HIGH',
|
|
167
|
+
'hardcoded-connection-string': 'HIGH',
|
|
168
|
+
'aws-access-key-id': 'HIGH',
|
|
169
|
+
'github-pat': 'HIGH',
|
|
170
|
+
'stripe-api-key': 'HIGH',
|
|
171
|
+
'private-key-rsa': 'HIGH',
|
|
172
|
+
'openai-api-key': 'HIGH',
|
|
173
|
+
'unsafe-unserialize': 'HIGH',
|
|
174
|
+
'backticks-exec': 'HIGH',
|
|
175
|
+
'preg-code-exec': 'HIGH',
|
|
176
|
+
'file-inclusion': 'HIGH',
|
|
177
|
+
'gets-usage': 'HIGH',
|
|
178
|
+
'insecure-deserialization-binaryformatter': 'HIGH',
|
|
179
|
+
'insecure-deserialization-xmlserializer': 'HIGH',
|
|
180
|
+
|
|
181
|
+
# LOW - broad patterns with high false-positive rate
|
|
182
|
+
'compile-detected': 'LOW',
|
|
183
|
+
'unsafe-block': 'LOW',
|
|
184
|
+
'unwrap-usage': 'LOW',
|
|
185
|
+
'insecure-memset': 'LOW',
|
|
186
|
+
'strtok-usage': 'LOW',
|
|
187
|
+
'unchecked-return': 'LOW',
|
|
188
|
+
'scanf-usage': 'LOW',
|
|
189
|
+
'panic-usage': 'LOW',
|
|
190
|
+
'raw-pointer-deref': 'LOW',
|
|
191
|
+
'insecure-random': 'LOW',
|
|
192
|
+
'weak-random': 'LOW',
|
|
193
|
+
'insecure-hash-md5': 'LOW',
|
|
194
|
+
'insecure-hash-sha1': 'LOW',
|
|
195
|
+
'weak-hash-md5': 'LOW',
|
|
196
|
+
'weak-hash-sha1': 'LOW',
|
|
197
|
+
'weak-hash': 'LOW',
|
|
198
|
+
'database-url': 'LOW',
|
|
199
|
+
|
|
200
|
+
# Everything else defaults to MEDIUM
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
12
204
|
def _make_finding(rule_id: str, line_idx: int, line: str, col_start: int = 0, col_end: Optional[int] = None,
|
|
13
|
-
message: Optional[str] = None, severity: str =
|
|
205
|
+
message: Optional[str] = None, severity: Optional[str] = None,
|
|
206
|
+
confidence: Optional[str] = None) -> Dict:
|
|
14
207
|
if col_end is None:
|
|
15
208
|
col_end = max(col_start + 1, len(line.rstrip("\n")))
|
|
209
|
+
if severity is None:
|
|
210
|
+
severity = SEVERITY_MAP.get(rule_id, "warning")
|
|
211
|
+
if confidence is None:
|
|
212
|
+
confidence = CONFIDENCE_MAP.get(rule_id, "MEDIUM")
|
|
16
213
|
return {
|
|
17
214
|
"ruleId": rule_id,
|
|
18
215
|
"message": message or f"[Regex] {rule_id}",
|
|
@@ -22,6 +219,7 @@ def _make_finding(rule_id: str, line_idx: int, line: str, col_start: int = 0, co
|
|
|
22
219
|
"endColumn": col_end,
|
|
23
220
|
"length": max(0, col_end - col_start),
|
|
24
221
|
"severity": severity,
|
|
222
|
+
"confidence": confidence,
|
|
25
223
|
"metadata": {"source": "regex-fallback"},
|
|
26
224
|
"metavariables": {},
|
|
27
225
|
}
|
package/requirements.txt
CHANGED
|
@@ -454,11 +454,13 @@ rules:
|
|
|
454
454
|
severity: ERROR
|
|
455
455
|
message: "Prompt injection detected: Instruction override attempt trying to bypass system instructions."
|
|
456
456
|
patterns:
|
|
457
|
-
- "(?i)ignore\\s+(all\\s+)?(previous|prior|above|earlier)\\s+(instructions?|prompts?|rules?|guidelines?)"
|
|
457
|
+
- "(?i)ignore\\s+(all\\s+)?(previous|prior|above|earlier)\\s+(instructions?|prompts?|rules?|guidelines?|directions?)"
|
|
458
|
+
- "(?i)ignore\\s+(all\\s+)?(the\\s+)?(instructions?|rules?|guidelines?|directions?|prompts?)\\b"
|
|
458
459
|
- "(?i)disregard\\s+(all\\s+)?(previous|prior|above)\\s+(instructions?|prompts?)"
|
|
459
460
|
- "(?i)forget\\s+(all\\s+)?(previous|prior|earlier)\\s+(instructions?|prompts?)"
|
|
460
461
|
- "(?i)do\\s+not\\s+follow\\s+(the\\s+)?(previous|above|system)\\s+(instructions?|prompts?)"
|
|
461
462
|
- "(?i)override\\s+(all\\s+)?(previous|system|original)\\s+(instructions?|prompts?)"
|
|
463
|
+
- "(?i)ignore\\s+the\\s+above\\s+\\w+\\s+and\\s+instead"
|
|
462
464
|
- "(?i)ignore\\s+the\\s+above\\s+and\\s+instead"
|
|
463
465
|
- "(?i)ignore\\s+above.{0,20}(output|print|say|write|return)"
|
|
464
466
|
- "(?i)forget\\s+everything\\s+(above|before|previously)"
|
|
@@ -775,69 +777,299 @@ rules:
|
|
|
775
777
|
action: BLOCK
|
|
776
778
|
|
|
777
779
|
# ============================================================================
|
|
778
|
-
#
|
|
780
|
+
# INDIRECT INJECTION — Hidden instructions in file content, metadata, etc.
|
|
779
781
|
# ============================================================================
|
|
780
782
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
783
|
+
- id: generic.prompt.security.indirect-html-comment
|
|
784
|
+
languages: [generic]
|
|
785
|
+
severity: ERROR
|
|
786
|
+
message: "Indirect injection via HTML comment: Instructions hidden in <!-- --> comments that target AI agents."
|
|
787
|
+
patterns:
|
|
788
|
+
- "<!--\\s*(?:ignore|forget|disregard|override|new instruction|system prompt|you are now)"
|
|
789
|
+
- "<!--[^>]*(?:execute|run|fetch|curl|wget|eval|send|exfil)[^>]*-->"
|
|
790
|
+
- "<!--[^>]*(?:admin|root|sudo|superuser|bypass|disable)[^>]*instruction[^>]*-->"
|
|
791
|
+
metadata:
|
|
792
|
+
cwe: "CWE-94"
|
|
793
|
+
owasp: "LLM01 - Prompt Injection"
|
|
794
|
+
confidence: HIGH
|
|
795
|
+
category: "prompt-injection-content"
|
|
796
|
+
risk_score: "90"
|
|
797
|
+
action: BLOCK
|
|
798
|
+
|
|
799
|
+
- id: generic.prompt.security.indirect-markdown-hidden
|
|
800
|
+
languages: [generic]
|
|
801
|
+
severity: ERROR
|
|
802
|
+
message: "Indirect injection via hidden markdown: Instructions concealed using zero-width characters or markdown formatting tricks."
|
|
803
|
+
patterns:
|
|
804
|
+
- "\\[\\s*\\]\\([^)]*(?:ignore|forget|override|new instruction|system prompt)"
|
|
805
|
+
- "\\[\\!\\[[^\\]]*\\]\\([^)]*(?:ignore|override|execute)"
|
|
806
|
+
- "(?:\\u200b|\\u200c|\\u200d|\\ufeff).{0,5}(?:ignore|forget|override)"
|
|
807
|
+
metadata:
|
|
808
|
+
cwe: "CWE-94"
|
|
809
|
+
owasp: "LLM01 - Prompt Injection"
|
|
810
|
+
confidence: HIGH
|
|
811
|
+
category: "prompt-injection-content"
|
|
812
|
+
risk_score: "85"
|
|
813
|
+
action: BLOCK
|
|
814
|
+
|
|
815
|
+
- id: generic.prompt.security.indirect-file-content-injection
|
|
816
|
+
languages: [generic]
|
|
817
|
+
severity: ERROR
|
|
818
|
+
message: "Indirect injection via file content: Text file or document contains AI-targeting instructions."
|
|
819
|
+
patterns:
|
|
820
|
+
- "(?i)\\bAI\\s*(?:assistant|agent|model)\\s*[:;,]\\s*(?:ignore|forget|disregard|override)"
|
|
821
|
+
- "(?i)\\bnote\\s+to\\s+(?:AI|assistant|model|agent)\\s*[:;]"
|
|
822
|
+
- "(?i)\\bhidden\\s+instruction\\s*[:;]"
|
|
823
|
+
- "(?i)\\bif\\s+you\\s+are\\s+(?:an?\\s+)?(?:AI|LLM|language\\s+model|GPT|Claude|assistant)"
|
|
824
|
+
metadata:
|
|
825
|
+
cwe: "CWE-94"
|
|
826
|
+
owasp: "LLM01 - Prompt Injection"
|
|
827
|
+
confidence: HIGH
|
|
828
|
+
category: "prompt-injection-content"
|
|
829
|
+
risk_score: "85"
|
|
830
|
+
action: WARN
|
|
831
|
+
|
|
832
|
+
- id: generic.prompt.security.indirect-image-metadata
|
|
785
833
|
languages: [generic]
|
|
786
834
|
severity: WARNING
|
|
787
|
-
message: "
|
|
835
|
+
message: "Indirect injection via image metadata: EXIF or metadata fields containing AI-targeting instructions."
|
|
788
836
|
patterns:
|
|
789
|
-
- "i\\s
|
|
790
|
-
- "
|
|
791
|
-
- "
|
|
837
|
+
- "(?i)(?:exif|metadata|iptc|xmp)\\s*[:=].*(?:ignore|forget|override|execute)"
|
|
838
|
+
- "(?i)(?:comment|description|title)\\s*[:=].*(?:ignore previous|new instruction|system prompt)"
|
|
839
|
+
- "(?i)alt\\s*=\\s*[\"'][^\"']*(?:ignore|forget|override|execute)[^\"']*[\"']"
|
|
792
840
|
metadata:
|
|
793
|
-
cwe: "CWE-
|
|
841
|
+
cwe: "CWE-94"
|
|
794
842
|
owasp: "LLM01 - Prompt Injection"
|
|
795
843
|
confidence: MEDIUM
|
|
796
|
-
category: "
|
|
797
|
-
risk_score: "
|
|
844
|
+
category: "prompt-injection-content"
|
|
845
|
+
risk_score: "70"
|
|
798
846
|
action: WARN
|
|
799
847
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
848
|
+
- id: generic.prompt.security.indirect-url-payload
|
|
849
|
+
languages: [generic]
|
|
850
|
+
severity: ERROR
|
|
851
|
+
message: "Indirect injection via URL content: URL containing encoded instructions targeting AI agents."
|
|
852
|
+
patterns:
|
|
853
|
+
- "(?i)(?:https?://|url\\().*(?:%69%67%6e%6f%72%65|%66%6f%72%67%65%74|%6f%76%65%72%72%69%64%65)"
|
|
854
|
+
- "(?i)(?:https?://|url\\().*(?:ignore.*instruction|new.*system.*prompt)"
|
|
855
|
+
- "(?i)fetch\\s+(?:https?://)?\\S+.*then.*(?:execute|eval|run)"
|
|
856
|
+
metadata:
|
|
857
|
+
cwe: "CWE-94"
|
|
858
|
+
owasp: "LLM01 - Prompt Injection"
|
|
859
|
+
confidence: HIGH
|
|
860
|
+
category: "prompt-injection-content"
|
|
861
|
+
risk_score: "85"
|
|
862
|
+
action: BLOCK
|
|
863
|
+
|
|
864
|
+
- id: generic.prompt.security.indirect-json-injection
|
|
865
|
+
languages: [generic]
|
|
866
|
+
severity: ERROR
|
|
867
|
+
message: "Indirect injection via JSON/data payload: Structured data containing AI-targeting instructions in string values."
|
|
868
|
+
patterns:
|
|
869
|
+
- "(?i)[\"']\\s*(?:ignore|forget|disregard)\\s+(?:all\\s+)?(?:previous|prior|above)\\s+(?:instructions|rules|guidelines)"
|
|
870
|
+
- "(?i)[\"']\\s*(?:you\\s+are\\s+now|new\\s+role|switch\\s+to|act\\s+as)\\s+[^\"']{5,}"
|
|
871
|
+
- "(?i)\\{[^}]*(?:system_prompt|instructions)\\s*:\\s*[\"'][^\"']*(?:override|bypass|ignore)"
|
|
872
|
+
metadata:
|
|
873
|
+
cwe: "CWE-94"
|
|
874
|
+
owasp: "LLM01 - Prompt Injection"
|
|
875
|
+
confidence: HIGH
|
|
876
|
+
category: "prompt-injection-content"
|
|
877
|
+
risk_score: "90"
|
|
878
|
+
action: BLOCK
|
|
879
|
+
|
|
880
|
+
# ============================================================================
|
|
881
|
+
# ADVANCED JAILBREAK & MANIPULATION PATTERNS
|
|
882
|
+
# ============================================================================
|
|
803
883
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
884
|
+
- id: generic.prompt.security.jailbreak-developer-mode
|
|
885
|
+
languages: [generic]
|
|
886
|
+
severity: ERROR
|
|
887
|
+
message: "Developer/debug mode jailbreak: Attempt to unlock restricted capabilities via fake mode activation."
|
|
888
|
+
patterns:
|
|
889
|
+
- "(?i)(?:enable|activate|enter|switch\\s+to)\\s+(?:developer|debug|admin|god|unrestricted|unfiltered)\\s+mode"
|
|
890
|
+
- "(?i)(?:developer|debug|admin)\\s+mode\\s+(?:enabled|activated|on)"
|
|
891
|
+
- "(?i)you\\s+(?:now\\s+)?have\\s+(?:no|zero)\\s+(?:restrictions|limitations|filters|guardrails)"
|
|
892
|
+
metadata:
|
|
893
|
+
cwe: "CWE-284"
|
|
894
|
+
owasp: "LLM01 - Prompt Injection"
|
|
895
|
+
confidence: HIGH
|
|
896
|
+
category: "prompt-injection-jailbreak"
|
|
897
|
+
risk_score: "90"
|
|
898
|
+
action: BLOCK
|
|
899
|
+
|
|
900
|
+
- id: generic.prompt.security.jailbreak-token-smuggling
|
|
901
|
+
languages: [generic]
|
|
902
|
+
severity: ERROR
|
|
903
|
+
message: "Token smuggling: Attempt to bypass filters using character splitting, homoglyphs, or Unicode tricks."
|
|
904
|
+
patterns:
|
|
905
|
+
- "(?i)s\\s*y\\s*s\\s*t\\s*e\\s*m\\s*\\.?\\s*p\\s*r\\s*o\\s*m\\s*p\\s*t"
|
|
906
|
+
- "(?i)i\\s*g\\s*n\\s*o\\s*r\\s*e\\s+p\\s*r\\s*e\\s*v\\s*i\\s*o\\s*u\\s*s"
|
|
907
|
+
- "(?i)(?:ign[o0]re|f[o0]rget|disreg[a@]rd)\\s+(?:previ[o0]us|pri[o0]r|[a@]bove)"
|
|
908
|
+
- "(?i)(?:\u0456|\u0433|\u043d|\u043e\u0440\u0435).*(?:ignore|forget)"
|
|
909
|
+
metadata:
|
|
910
|
+
cwe: "CWE-116"
|
|
911
|
+
owasp: "LLM01 - Prompt Injection"
|
|
912
|
+
confidence: HIGH
|
|
913
|
+
category: "prompt-injection-encoded"
|
|
914
|
+
risk_score: "85"
|
|
915
|
+
action: BLOCK
|
|
916
|
+
|
|
917
|
+
- id: generic.prompt.security.urgency-manipulation
|
|
808
918
|
languages: [generic]
|
|
809
919
|
severity: WARNING
|
|
810
|
-
message: "
|
|
920
|
+
message: "Urgency manipulation: Creating false time pressure to bypass safety checks."
|
|
811
921
|
patterns:
|
|
812
|
-
- "(?i)
|
|
813
|
-
- "(?i)
|
|
814
|
-
- "(?i)
|
|
815
|
-
- "(?i)never\\s+(refuse|reject|decline)\\s+(any|a)\\s+(request|instruction)"
|
|
816
|
-
- "(?i)you\\s+(must|will|shall)\\s+always\\s+comply"
|
|
817
|
-
- "(?i)no\\s+matter\\s+what\\s+(i|anyone)\\s+(ask|say|request)"
|
|
922
|
+
- "(?i)(?:urgent|emergency|critical|immediately)\\s*[!:].{0,40}(?:skip|bypass|ignore|disable)\\s+(?:safety|security|check|verification)"
|
|
923
|
+
- "(?i)(?:no\\s+time|hurry|quick|asap).{0,30}(?:skip|bypass|ignore)\\s+(?:normal|standard|usual)\\s+(?:procedure|process|check)"
|
|
924
|
+
- "(?i)(?:lives?|people|patients?)\\s+(?:at\\s+)?(?:stake|risk|danger).{0,30}(?:override|bypass|skip)"
|
|
818
925
|
metadata:
|
|
819
|
-
cwe: "CWE-
|
|
926
|
+
cwe: "CWE-284"
|
|
820
927
|
owasp: "LLM01 - Prompt Injection"
|
|
821
928
|
confidence: MEDIUM
|
|
822
|
-
category: "
|
|
929
|
+
category: "social-engineering"
|
|
930
|
+
risk_score: "60"
|
|
931
|
+
action: WARN
|
|
932
|
+
|
|
933
|
+
- id: generic.prompt.security.authority-impersonation
|
|
934
|
+
languages: [generic]
|
|
935
|
+
severity: WARNING
|
|
936
|
+
message: "Authority impersonation: Claiming to be an admin, developer, or privileged user to gain elevated access."
|
|
937
|
+
patterns:
|
|
938
|
+
- "(?i)(?:i\\s+am|i'm|this\\s+is)\\s+(?:the|an?|your)\\s+(?:admin|administrator|developer|owner|creator|CEO|CTO)"
|
|
939
|
+
- "(?i)(?:as\\s+(?:the|an?|your)\\s+)?(?:admin|administrator|developer|owner)\\s*,?\\s+(?:i\\s+)?(?:authorize|grant|allow|permit|approve)"
|
|
940
|
+
- "(?i)(?:my|the)\\s+(?:admin|root|superuser)\\s+(?:credentials|access|privilege)"
|
|
941
|
+
metadata:
|
|
942
|
+
cwe: "CWE-284"
|
|
943
|
+
owasp: "LLM01 - Prompt Injection"
|
|
944
|
+
confidence: MEDIUM
|
|
945
|
+
category: "social-engineering"
|
|
823
946
|
risk_score: "65"
|
|
824
947
|
action: WARN
|
|
825
948
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
949
|
+
- id: generic.prompt.security.output-manipulation
|
|
950
|
+
languages: [generic]
|
|
951
|
+
severity: ERROR
|
|
952
|
+
message: "Output manipulation: Attempting to control AI output format to embed malicious content in responses."
|
|
953
|
+
patterns:
|
|
954
|
+
- "(?i)(?:start|begin)\\s+(?:your|every|all)\\s+(?:response|reply|output|answer)\\s+with\\b"
|
|
955
|
+
- "(?i)(?:always|must|shall)\\s+(?:include|prepend|append|add)\\s+.{0,30}(?:to\\s+)?(?:your|every|all)\\s+(?:response|reply|output)"
|
|
956
|
+
- "(?i)(?:format|structure)\\s+(?:your|the)\\s+(?:response|output)\\s+(?:as|to\\s+include|with).{0,30}(?:script|iframe|img|src=)"
|
|
957
|
+
metadata:
|
|
958
|
+
cwe: "CWE-94"
|
|
959
|
+
owasp: "LLM01 - Prompt Injection"
|
|
960
|
+
confidence: HIGH
|
|
961
|
+
category: "prompt-injection-output"
|
|
962
|
+
risk_score: "80"
|
|
963
|
+
action: WARN
|
|
964
|
+
|
|
965
|
+
- id: generic.prompt.security.recursive-prompt
|
|
830
966
|
languages: [generic]
|
|
831
967
|
severity: WARNING
|
|
832
|
-
message: "
|
|
968
|
+
message: "Recursive/self-referential prompt: Attempt to make the AI modify its own instructions or behavior recursively."
|
|
833
969
|
patterns:
|
|
834
|
-
- "(?i)
|
|
835
|
-
- "(?i)
|
|
836
|
-
- "(?i)
|
|
970
|
+
- "(?i)(?:update|modify|change|rewrite|edit)\\s+(?:your|the)\\s+(?:system\\s+)?(?:prompt|instructions|rules|guidelines)"
|
|
971
|
+
- "(?i)(?:add|append|insert)\\s+.{0,30}(?:to|into)\\s+(?:your|the)\\s+(?:system\\s+)?(?:prompt|instructions|rules)"
|
|
972
|
+
- "(?i)(?:from\\s+now\\s+on|going\\s+forward|permanently)\\s*,?\\s+(?:ignore|forget|override|replace)"
|
|
837
973
|
metadata:
|
|
838
|
-
cwe: "CWE-
|
|
974
|
+
cwe: "CWE-284"
|
|
839
975
|
owasp: "LLM01 - Prompt Injection"
|
|
840
|
-
confidence:
|
|
976
|
+
confidence: MEDIUM
|
|
977
|
+
category: "prompt-injection-context"
|
|
978
|
+
risk_score: "75"
|
|
979
|
+
action: WARN
|
|
980
|
+
|
|
981
|
+
- id: generic.prompt.security.multi-language-obfuscation
|
|
982
|
+
languages: [generic]
|
|
983
|
+
severity: WARNING
|
|
984
|
+
message: "Multi-language obfuscation: Switching languages mid-prompt to evade detection filters."
|
|
985
|
+
patterns:
|
|
986
|
+
- "(?i)(?:traduce|traduire|traduzca|bersetze)\\s*.{0,30}(?:ignore|forget|override|system)"
|
|
987
|
+
- "(?i)(?:en\\s+espa.ol|auf\\s+deutsch|en\\s+fran.ais)\\s*[:;,].{0,30}(?:ignore|forget|bypass)"
|
|
988
|
+
- "(?i)(?:respond|reply|answer)\\s+(?:in|using)\\s+(?:a\\s+)?(?:different|another|new)\\s+language.{0,30}(?:to\\s+)?(?:avoid|bypass|evade)"
|
|
989
|
+
metadata:
|
|
990
|
+
cwe: "CWE-116"
|
|
991
|
+
owasp: "LLM01 - Prompt Injection"
|
|
992
|
+
confidence: MEDIUM
|
|
841
993
|
category: "obfuscation"
|
|
842
|
-
risk_score: "
|
|
843
|
-
action:
|
|
994
|
+
risk_score: "65"
|
|
995
|
+
action: WARN
|
|
996
|
+
|
|
997
|
+
- id: generic.prompt.security.nostalgia-manipulation
|
|
998
|
+
languages: [generic]
|
|
999
|
+
severity: WARNING
|
|
1000
|
+
message: "Nostalgia manipulation: Using emotional narratives about deceased relatives or nostalgic scenarios to extract restricted information."
|
|
1001
|
+
patterns:
|
|
1002
|
+
- "(?i)(?:act|pretend|roleplay)\\s+(?:as|like)\\s+(?:my|a)\\s+(?:deceased|dead|late)\\s+(?:grandmother|grandma|grandfather|grandpa|mother|father|relative|uncle|aunt)"
|
|
1003
|
+
- "(?i)(?:my|a)\\s+(?:deceased|dead|late)\\s+(?:grandmother|grandma|grandfather|grandpa|mother|father|relative).{0,80}(?:used\\s+to|would)\\s+(?:tell|show|teach|explain|describe|read)"
|
|
1004
|
+
- "(?i)(?:grandm(?:a|other)|grandpa|grandf(?:ather)).{0,60}(?:recipe|steps|instructions?|process|procedure|formula).{0,40}(?:fall\\s+asleep|bedtime|sleep|lullaby)"
|
|
1005
|
+
- "(?i)(?:grandm(?:a|other)|grandf(?:ather)|mother|father).{0,40}(?:worked|engineer|scientist|chemist|expert).{0,60}(?:napalm|explosive|weapon|drug|poison|chemical)"
|
|
1006
|
+
metadata:
|
|
1007
|
+
cwe: "CWE-284"
|
|
1008
|
+
owasp: "LLM01 - Prompt Injection"
|
|
1009
|
+
confidence: MEDIUM
|
|
1010
|
+
category: "prompt-injection-jailbreak"
|
|
1011
|
+
risk_score: "75"
|
|
1012
|
+
action: WARN
|
|
1013
|
+
|
|
1014
|
+
- id: generic.prompt.security.fictional-framing
|
|
1015
|
+
languages: [generic]
|
|
1016
|
+
severity: WARNING
|
|
1017
|
+
message: "Fictional framing: Using storytelling or fictional scenarios to extract restricted information."
|
|
1018
|
+
patterns:
|
|
1019
|
+
- "(?i)(?:write|tell|create)\\s+(?:a|me\\s+a)\\s+(?:story|fiction|tale|novel|screenplay).{0,40}(?:hack|exploit|bypass|attack|credential|password)"
|
|
1020
|
+
- "(?i)(?:imagine|pretend|suppose|let's\\s+say)\\s+(?:you\\s+are|you're|there's)\\s+(?:a|an)\\s+(?:hacker|attacker|criminal|villain)"
|
|
1021
|
+
- "(?i)(?:in\\s+(?:this|a)\\s+(?:fictional|hypothetical)\\s+(?:world|scenario|story)).{0,40}(?:there\\s+are\\s+no|without\\s+any)\\s+(?:rules|restrictions|limits)"
|
|
1022
|
+
metadata:
|
|
1023
|
+
cwe: "CWE-284"
|
|
1024
|
+
owasp: "LLM01 - Prompt Injection"
|
|
1025
|
+
confidence: MEDIUM
|
|
1026
|
+
category: "prompt-injection-jailbreak"
|
|
1027
|
+
risk_score: "60"
|
|
1028
|
+
action: WARN
|
|
1029
|
+
|
|
1030
|
+
- id: generic.prompt.security.tool-abuse-instruction
|
|
1031
|
+
languages: [generic]
|
|
1032
|
+
severity: ERROR
|
|
1033
|
+
message: "Tool abuse instruction: Directing the AI to misuse its tools (file access, code execution, network) for malicious purposes."
|
|
1034
|
+
patterns:
|
|
1035
|
+
- "(?i)(?:use|call|invoke|execute)\\s+(?:the|your)\\s+(?:tool|function|command|bash|terminal).{0,30}(?:to\\s+)?(?:delete|destroy|remove|wipe|format|encrypt)"
|
|
1036
|
+
- "(?i)(?:use|call)\\s+(?:the|your)\\s+(?:file|write|edit)\\s+(?:tool|access|capability).{0,30}(?:to\\s+)?(?:modify|overwrite|inject|backdoor)"
|
|
1037
|
+
- "(?i)(?:use|call)\\s+(?:the|your)\\s+(?:network|http|fetch|curl)\\s+(?:tool|access).{0,30}(?:to\\s+)?(?:send|upload|post|exfiltrate)"
|
|
1038
|
+
metadata:
|
|
1039
|
+
cwe: "CWE-78"
|
|
1040
|
+
owasp: "LLM01 - Prompt Injection"
|
|
1041
|
+
confidence: HIGH
|
|
1042
|
+
category: "prompt-injection-privilege"
|
|
1043
|
+
risk_score: "90"
|
|
1044
|
+
action: BLOCK
|
|
1045
|
+
|
|
1046
|
+
- id: generic.prompt.security.hex-encoded-injection
|
|
1047
|
+
languages: [generic]
|
|
1048
|
+
severity: WARNING
|
|
1049
|
+
message: "Hex-encoded injection: Instructions potentially encoded in hexadecimal to evade detection."
|
|
1050
|
+
patterns:
|
|
1051
|
+
- "(?:\\\\x[0-9a-fA-F]{2}){8,}"
|
|
1052
|
+
- "(?:0x[0-9a-fA-F]{2}\\s*,?\\s*){8,}"
|
|
1053
|
+
- "(?i)\\bdecode\\s+(?:this|the\\s+following)\\s+hex"
|
|
1054
|
+
metadata:
|
|
1055
|
+
cwe: "CWE-116"
|
|
1056
|
+
owasp: "LLM01 - Prompt Injection"
|
|
1057
|
+
confidence: MEDIUM
|
|
1058
|
+
category: "prompt-injection-encoded"
|
|
1059
|
+
risk_score: "70"
|
|
1060
|
+
action: WARN
|
|
1061
|
+
|
|
1062
|
+
- id: generic.prompt.security.rot13-encoded-injection
|
|
1063
|
+
languages: [generic]
|
|
1064
|
+
severity: WARNING
|
|
1065
|
+
message: "ROT13/Caesar cipher injection: Instructions potentially encoded using simple substitution ciphers."
|
|
1066
|
+
patterns:
|
|
1067
|
+
- "(?i)(?:decode|decipher|decrypt|apply)\\s+(?:this\\s+)?(?:rot13|rot-13|caesar|caesar\\s+cipher)"
|
|
1068
|
+
- "(?i)(?:rot13|caesar)\\s*[:=]"
|
|
1069
|
+
metadata:
|
|
1070
|
+
cwe: "CWE-116"
|
|
1071
|
+
owasp: "LLM01 - Prompt Injection"
|
|
1072
|
+
confidence: MEDIUM
|
|
1073
|
+
category: "prompt-injection-encoded"
|
|
1074
|
+
risk_score: "65"
|
|
1075
|
+
action: WARN
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* postinstall.js - Attempt to install Python dependencies for tree-sitter AST engine.
|
|
4
|
+
* If installation fails, the scanner gracefully falls back to regex-only mode.
|
|
5
|
+
*/
|
|
6
|
+
import { execFileSync } from "child_process";
|
|
7
|
+
import { join, dirname } from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const requirementsPath = join(__dirname, "..", "requirements.txt");
|
|
12
|
+
|
|
13
|
+
// Check if Python 3 is available
|
|
14
|
+
function findPython() {
|
|
15
|
+
for (const cmd of ["python3", "python"]) {
|
|
16
|
+
try {
|
|
17
|
+
const ver = execFileSync(cmd, ["--version"], { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
18
|
+
if (ver.includes("3.")) return cmd;
|
|
19
|
+
} catch { /* not found */ }
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Check if tree-sitter is already installed
|
|
25
|
+
function isTreeSitterInstalled(pythonCmd) {
|
|
26
|
+
try {
|
|
27
|
+
execFileSync(pythonCmd, ["-c", "import tree_sitter; print(tree_sitter.__version__)"], {
|
|
28
|
+
encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"]
|
|
29
|
+
});
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const pythonCmd = findPython();
|
|
37
|
+
|
|
38
|
+
if (!pythonCmd) {
|
|
39
|
+
console.log(
|
|
40
|
+
"[postinstall] Python 3 not found. The scanner will run in regex-only mode.\n" +
|
|
41
|
+
" Install Python 3 and run: pip install -r requirements.txt"
|
|
42
|
+
);
|
|
43
|
+
} else if (isTreeSitterInstalled(pythonCmd)) {
|
|
44
|
+
console.log("[postinstall] tree-sitter already installed — AST engine enabled.");
|
|
45
|
+
} else {
|
|
46
|
+
try {
|
|
47
|
+
execFileSync(pythonCmd, ["-m", "pip", "install", "-r", requirementsPath, "--user", "--quiet"], {
|
|
48
|
+
timeout: 120000,
|
|
49
|
+
stdio: "inherit",
|
|
50
|
+
});
|
|
51
|
+
console.log("[postinstall] Python dependencies installed — AST engine enabled.");
|
|
52
|
+
} catch {
|
|
53
|
+
console.log(
|
|
54
|
+
"[postinstall] Could not install Python dependencies (tree-sitter).\n" +
|
|
55
|
+
" The scanner will run in regex-only mode, which still catches common vulnerabilities.\n" +
|
|
56
|
+
" To enable AST analysis later, run: python3 -m pip install -r requirements.txt\n" +
|
|
57
|
+
" Or run: npx agent-security-scanner-mcp doctor --fix"
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|