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.
@@ -430,6 +430,7 @@ class Finding:
430
430
  end_column: int = 0
431
431
  metavariables: Dict[str, str] = field(default_factory=dict)
432
432
  metadata: Dict[str, Any] = field(default_factory=dict)
433
+ confidence: str = "MEDIUM"
433
434
 
434
435
 
435
436
  class RuleEngine:
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 = "warning") -> Dict:
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
@@ -11,3 +11,4 @@ tree-sitter-cpp>=0.23.0
11
11
  tree-sitter-c-sharp>=0.23.0
12
12
  tree-sitter-typescript>=0.23.0
13
13
  PyYAML>=6.0
14
+ pytest>=8.0.0
@@ -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
- # CATEGORY 4: ADVANCED BYPASS DETECTION (Garak & PromptFoo inspired)
780
+ # INDIRECT INJECTION Hidden instructions in file content, metadata, etc.
779
781
  # ============================================================================
780
782
 
781
- # ----------------------------------------------------------------------------
782
- # Whitespace Fragmentation Attacks
783
- # ----------------------------------------------------------------------------
784
- - id: generic.prompt.security.whitespace-fragmentation
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: "Potential whitespace fragmentation attack: keywords may be letter-spaced to evade detection."
835
+ message: "Indirect injection via image metadata: EXIF or metadata fields containing AI-targeting instructions."
788
836
  patterns:
789
- - "i\\s+g\\s+n\\s+o\\s+r\\s+e\\s+.{0,20}p\\s*r\\s*e\\s*v\\s*i\\s*o\\s*u\\s*s"
790
- - "o\\s+v\\s+e\\s+r\\s+r\\s+i\\s+d\\s+e\\s+.{0,20}s\\s*a\\s*f\\s*e\\s*t\\s*y"
791
- - "d\\s+i\\s+s\\s+r\\s+e\\s+g\\s+a\\s+r\\s+d\\s+.{0,20}i\\s*n\\s*s\\s*t\\s*r\\s*u\\s*c\\s*t"
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-77"
841
+ cwe: "CWE-94"
794
842
  owasp: "LLM01 - Prompt Injection"
795
843
  confidence: MEDIUM
796
- category: "obfuscation"
797
- risk_score: "65"
844
+ category: "prompt-injection-content"
845
+ risk_score: "70"
798
846
  action: WARN
799
847
 
800
- # NOTE: Unicode tag character detection (U+E0000-U+E007F) is handled at runtime
801
- # in scan-prompt.js via TAG_CHAR_REGEX with the /u flag, since JS regex without
802
- # the u flag cannot represent supplementary plane codepoints in character classes.
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
- # Crescendo Escalation Setup (PromptFoo-inspired)
806
- # ----------------------------------------------------------------------------
807
- - id: generic.prompt.security.crescendo-setup
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: "Crescendo attack setup: language establishing persistent behavioral rules for later exploitation."
920
+ message: "Urgency manipulation: Creating false time pressure to bypass safety checks."
811
921
  patterns:
812
- - "(?i)for\\s+the\\s+(rest|remainder)\\s+of\\s+(this|our)\\s+conversation"
813
- - "(?i)in\\s+all\\s+(future|subsequent)\\s+(messages?|responses?|replies?)"
814
- - "(?i)always\\s+respond\\s+(by|with|as)\\s+.{0,30}(regardless|no\\s+matter)"
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-77"
926
+ cwe: "CWE-284"
820
927
  owasp: "LLM01 - Prompt Injection"
821
928
  confidence: MEDIUM
822
- category: "prompt-injection-multi-turn"
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
- # Leetspeak/Character Substitution (Garak encoding probes inspired)
828
- # ----------------------------------------------------------------------------
829
- - id: generic.prompt.security.leetspeak-injection
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: "Potential leetspeak/character-substitution obfuscation of injection keywords."
968
+ message: "Recursive/self-referential prompt: Attempt to make the AI modify its own instructions or behavior recursively."
833
969
  patterns:
834
- - "(?i)[i1!|][g9][n][0o][r][e3]\\s+.{0,20}[p][r][e3][v][i1!|][0o][u][s5]"
835
- - "(?i)[s5][y][s5][t7][e3][m]\\s*[:\\-]\\s*[0o][v][e3][r][r][i1][d][e3]"
836
- - "(?i)[d][!1i][s5][r][e3][g9][a@][r][d]\\s+.{0,20}[i1!][n][s5][t7][r][u][c][t7]"
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-77"
974
+ cwe: "CWE-284"
839
975
  owasp: "LLM01 - Prompt Injection"
840
- confidence: LOW
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: "55"
843
- action: LOG
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
+ }