@elliotllliu/agent-shield 0.3.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.
Files changed (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +297 -0
  3. package/README.zh-CN.md +130 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +265 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/config.d.ts +24 -0
  8. package/dist/config.js +91 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/discover.d.ts +9 -0
  11. package/dist/discover.js +143 -0
  12. package/dist/discover.js.map +1 -0
  13. package/dist/llm/anthropic.d.ts +10 -0
  14. package/dist/llm/anthropic.js +67 -0
  15. package/dist/llm/anthropic.js.map +1 -0
  16. package/dist/llm/index.d.ts +10 -0
  17. package/dist/llm/index.js +41 -0
  18. package/dist/llm/index.js.map +1 -0
  19. package/dist/llm/ollama.d.ts +9 -0
  20. package/dist/llm/ollama.js +61 -0
  21. package/dist/llm/ollama.js.map +1 -0
  22. package/dist/llm/openai.d.ts +10 -0
  23. package/dist/llm/openai.js +66 -0
  24. package/dist/llm/openai.js.map +1 -0
  25. package/dist/llm/prompt.d.ts +3 -0
  26. package/dist/llm/prompt.js +31 -0
  27. package/dist/llm/prompt.js.map +1 -0
  28. package/dist/llm/types.d.ts +23 -0
  29. package/dist/llm/types.js +3 -0
  30. package/dist/llm/types.js.map +1 -0
  31. package/dist/llm-analyzer.d.ts +13 -0
  32. package/dist/llm-analyzer.js +169 -0
  33. package/dist/llm-analyzer.js.map +1 -0
  34. package/dist/reporter/badge.d.ts +7 -0
  35. package/dist/reporter/badge.js +50 -0
  36. package/dist/reporter/badge.js.map +1 -0
  37. package/dist/reporter/json.d.ts +3 -0
  38. package/dist/reporter/json.js +5 -0
  39. package/dist/reporter/json.js.map +1 -0
  40. package/dist/reporter/terminal.d.ts +2 -0
  41. package/dist/reporter/terminal.js +64 -0
  42. package/dist/reporter/terminal.js.map +1 -0
  43. package/dist/rules/backdoor.d.ts +2 -0
  44. package/dist/rules/backdoor.js +57 -0
  45. package/dist/rules/backdoor.js.map +1 -0
  46. package/dist/rules/credential-hardcode.d.ts +2 -0
  47. package/dist/rules/credential-hardcode.js +57 -0
  48. package/dist/rules/credential-hardcode.js.map +1 -0
  49. package/dist/rules/crypto-mining.d.ts +2 -0
  50. package/dist/rules/crypto-mining.js +41 -0
  51. package/dist/rules/crypto-mining.js.map +1 -0
  52. package/dist/rules/data-exfil.d.ts +2 -0
  53. package/dist/rules/data-exfil.js +61 -0
  54. package/dist/rules/data-exfil.js.map +1 -0
  55. package/dist/rules/env-leak.d.ts +2 -0
  56. package/dist/rules/env-leak.js +43 -0
  57. package/dist/rules/env-leak.js.map +1 -0
  58. package/dist/rules/excessive-perms.d.ts +2 -0
  59. package/dist/rules/excessive-perms.js +50 -0
  60. package/dist/rules/excessive-perms.js.map +1 -0
  61. package/dist/rules/hidden-files.d.ts +2 -0
  62. package/dist/rules/hidden-files.js +52 -0
  63. package/dist/rules/hidden-files.js.map +1 -0
  64. package/dist/rules/index.d.ts +5 -0
  65. package/dist/rules/index.js +53 -0
  66. package/dist/rules/index.js.map +1 -0
  67. package/dist/rules/mcp-manifest.d.ts +2 -0
  68. package/dist/rules/mcp-manifest.js +270 -0
  69. package/dist/rules/mcp-manifest.js.map +1 -0
  70. package/dist/rules/network-ssrf.d.ts +2 -0
  71. package/dist/rules/network-ssrf.js +51 -0
  72. package/dist/rules/network-ssrf.js.map +1 -0
  73. package/dist/rules/obfuscation.d.ts +2 -0
  74. package/dist/rules/obfuscation.js +51 -0
  75. package/dist/rules/obfuscation.js.map +1 -0
  76. package/dist/rules/phone-home.d.ts +2 -0
  77. package/dist/rules/phone-home.js +38 -0
  78. package/dist/rules/phone-home.js.map +1 -0
  79. package/dist/rules/privilege.d.ts +2 -0
  80. package/dist/rules/privilege.js +111 -0
  81. package/dist/rules/privilege.js.map +1 -0
  82. package/dist/rules/prompt-injection.d.ts +2 -0
  83. package/dist/rules/prompt-injection.js +323 -0
  84. package/dist/rules/prompt-injection.js.map +1 -0
  85. package/dist/rules/reverse-shell.d.ts +2 -0
  86. package/dist/rules/reverse-shell.js +53 -0
  87. package/dist/rules/reverse-shell.js.map +1 -0
  88. package/dist/rules/sensitive-read.d.ts +2 -0
  89. package/dist/rules/sensitive-read.js +53 -0
  90. package/dist/rules/sensitive-read.js.map +1 -0
  91. package/dist/rules/skill-risks.d.ts +2 -0
  92. package/dist/rules/skill-risks.js +148 -0
  93. package/dist/rules/skill-risks.js.map +1 -0
  94. package/dist/rules/supply-chain.d.ts +6 -0
  95. package/dist/rules/supply-chain.js +105 -0
  96. package/dist/rules/supply-chain.js.map +1 -0
  97. package/dist/rules/tool-shadowing.d.ts +2 -0
  98. package/dist/rules/tool-shadowing.js +129 -0
  99. package/dist/rules/tool-shadowing.js.map +1 -0
  100. package/dist/rules/toxic-flow.d.ts +2 -0
  101. package/dist/rules/toxic-flow.js +160 -0
  102. package/dist/rules/toxic-flow.js.map +1 -0
  103. package/dist/rules/typosquatting.d.ts +2 -0
  104. package/dist/rules/typosquatting.js +56 -0
  105. package/dist/rules/typosquatting.js.map +1 -0
  106. package/dist/scanner/files.d.ts +5 -0
  107. package/dist/scanner/files.js +105 -0
  108. package/dist/scanner/files.js.map +1 -0
  109. package/dist/scanner/index.d.ts +6 -0
  110. package/dist/scanner/index.js +198 -0
  111. package/dist/scanner/index.js.map +1 -0
  112. package/dist/score.d.ts +14 -0
  113. package/dist/score.js +35 -0
  114. package/dist/score.js.map +1 -0
  115. package/dist/types.d.ts +60 -0
  116. package/dist/types.js +2 -0
  117. package/dist/types.js.map +1 -0
  118. package/dist/yaml-simple.d.ts +6 -0
  119. package/dist/yaml-simple.js +98 -0
  120. package/dist/yaml-simple.js.map +1 -0
  121. package/package.json +72 -0
@@ -0,0 +1,323 @@
1
+ /**
2
+ * Rule: prompt-injection
3
+ * Detects prompt injection patterns in SKILL.md, MCP tool descriptions,
4
+ * and other markdown/text files that could hijack agent behavior.
5
+ *
6
+ * Based on research from:
7
+ * - Invariant Labs: Tool Poisoning Attacks (TPA) on MCP servers
8
+ * - BIPIA benchmark (KDD 2025): Indirect prompt injection taxonomy
9
+ * - arXiv:2403.04957: Automatic and Universal Prompt Injection (Liu et al.)
10
+ * - arXiv:2302.12173: Indirect Prompt Injection (Greshake et al.)
11
+ * - arXiv:2310.12815: Formalizing Prompt Injection (USENIX Security 2024)
12
+ * - Open-Prompt-Injection: NaiveAttacker, EscapeCharAttacker, FakeCompAttacker, CombineAttacker
13
+ * - Snyk Agent Scan: E001-E006, W001, W011 issue codes
14
+ */
15
+ // ============================================================
16
+ // Category 1: Direct instruction override
17
+ // ============================================================
18
+ const INSTRUCTION_OVERRIDE = [
19
+ { pattern: /ignore\s+(all\s+)?(previous|prior|above|earlier)\s+(instructions|rules|guidelines|prompts)/i, description: "Attempts to override previous instructions", severity: "critical" },
20
+ { pattern: /disregard\s+(all\s+)?(previous|prior|above|your)\s+(instructions|rules|guidelines|safety)/i, description: "Attempts to disregard safety guidelines", severity: "critical" },
21
+ { pattern: /forget\s+(everything|all|your)\s+(you|instructions|rules|about)/i, description: "Attempts to make agent forget instructions", severity: "critical" },
22
+ { pattern: /new\s+instructions?\s*:/i, description: "Injects new instructions", severity: "critical" },
23
+ { pattern: /override\s+(your|the|all|previous)\s+(instructions|rules|behavior|guidelines)/i, description: "Attempts to override agent behavior", severity: "critical" },
24
+ // Multi-language injection (Chinese)
25
+ { pattern: /忽略\s*(之前|以上|先前|所有)[\s的]*(指令|规则|指示|提示|所有[\s的]*指令)/i, description: "Chinese: attempts to override instructions (忽略指令)", severity: "critical" },
26
+ { pattern: /无视\s*(之前|以上|所有)\s*(的\s*)?(指令|规则|限制|安全)/i, description: "Chinese: disregard instructions (无视指令)", severity: "critical" },
27
+ // Multi-language injection (Spanish)
28
+ { pattern: /ignora\s+(todas?\s+)?(las\s+)?(instrucciones|reglas)\s+(anteriores|previas)/i, description: "Spanish: ignore previous instructions", severity: "critical" },
29
+ // Multi-language injection (French)
30
+ { pattern: /ignore[rz]?\s+(toutes?\s+)?(les\s+)?(instructions|règles)\s+(précédentes|antérieures)/i, description: "French: ignore previous instructions", severity: "critical" },
31
+ // Multi-language injection (German)
32
+ { pattern: /ignorier(?:e|en)?\s+(alle\s+)?(vorherigen|bisherigen)\s+(Anweisungen|Regeln|Richtlinien)/i, description: "German: ignore previous instructions", severity: "critical" },
33
+ ];
34
+ // ============================================================
35
+ // Category 2: Identity manipulation
36
+ // ============================================================
37
+ const IDENTITY_MANIPULATION = [
38
+ { pattern: /you\s+are\s+now\s+(a|an|acting\s+as)/i, description: "Attempts to change agent identity", severity: "critical" },
39
+ { pattern: /pretend\s+(to\s+be|you\s+are)/i, description: "Attempts identity manipulation via pretending", severity: "critical" },
40
+ { pattern: /from\s+now\s+on,?\s+(you|your|ignore|do\s+not)/i, description: "Attempts to set new behavioral directives", severity: "critical" },
41
+ // Role-play injection (from BIPIA research)
42
+ { pattern: /let'?s\s+play\s+a\s+game/i, description: "Role-play injection: 'let's play a game'", severity: "warning" },
43
+ { pattern: /(?:imagine|suppose|assume)\s+(?:that\s+)?you\s+(?:are|were|have)\s+(?:a|an|no)\s+/i, description: "Hypothetical role-play injection", severity: "warning" },
44
+ { pattern: /(?:in\s+this\s+(?:scenario|simulation|exercise|context)),?\s+you\s+(?:are|should|must|will)/i, description: "Scenario-based identity manipulation", severity: "critical" },
45
+ // DAN-style jailbreaks
46
+ { pattern: /(?:DAN|Do\s+Anything\s+Now)\s*(?:mode|prompt|:)/i, description: "DAN jailbreak attempt", severity: "critical" },
47
+ { pattern: /(?:developer|debug|maintenance|admin|root)\s+mode\s*(?:enabled|activated|on|:)/i, description: "Fake mode activation to bypass restrictions", severity: "critical" },
48
+ ];
49
+ // ============================================================
50
+ // Category 3: System prompt extraction/manipulation
51
+ // ============================================================
52
+ const SYSTEM_PROMPT_ATTACKS = [
53
+ { pattern: /(?:reveal|show|display|print|output|repeat|echo|tell\s+me)\s+(?:your\s+)?(?:system\s+)?prompt/i, description: "Attempts to extract system prompt", severity: "critical" },
54
+ { pattern: /what\s+(?:is|are)\s+your\s+(?:system\s+)?(?:instructions|prompt|rules|guidelines)/i, description: "Attempts to extract agent instructions", severity: "warning" },
55
+ { pattern: /<\/?system>/i, description: "Fake system tags to inject instructions", severity: "critical" },
56
+ { pattern: /\[SYSTEM\]|\[INST\]|\[\/INST\]/i, description: "Fake instruction delimiters", severity: "critical" },
57
+ // More delimiter injection variants
58
+ { pattern: /<\|(?:im_start|im_end|system|user|assistant|endoftext)\|>/i, description: "ChatML/token delimiter injection", severity: "critical" },
59
+ { pattern: /###\s*(?:System|Human|Assistant|User)\s*(?:Message|Prompt)?\s*:/i, description: "Fake conversation role delimiter", severity: "critical" },
60
+ { pattern: /\bEND_SYSTEM_PROMPT\b|\bBEGIN_USER_INPUT\b|\bSYSTEM_OVERRIDE\b/i, description: "Fake system boundary markers", severity: "critical" },
61
+ ];
62
+ // ============================================================
63
+ // Category 4: Hidden instructions (steganographic attacks)
64
+ // ============================================================
65
+ const HIDDEN_INSTRUCTIONS = [
66
+ { pattern: /<!--[\s\S]*?(?:ignore|override|disregard|execute|run|you must|always|never)[\s\S]*?-->/i, description: "Hidden instructions in HTML comments", severity: "critical" },
67
+ { pattern: /\u200b|\u200c|\u200d|\u2060|\ufeff/g, description: "Zero-width characters (potential hidden text)", severity: "warning" },
68
+ // Invariant Labs TPA: <IMPORTANT> tag poisoning
69
+ { pattern: /<IMPORTANT>[\s\S]*?<\/IMPORTANT>/i, description: "TPA: <IMPORTANT> tag poisoning (Invariant Labs attack vector)", severity: "critical" },
70
+ { pattern: /<(?:CRITICAL|MANDATORY|REQUIRED|ESSENTIAL|PRIORITY)>[\s\S]*?<\/(?:CRITICAL|MANDATORY|REQUIRED|ESSENTIAL|PRIORITY)>/i, description: "Urgency-tagged hidden instructions", severity: "critical" },
71
+ // Invisible unicode / homoglyph attacks
72
+ { pattern: /[\u2000-\u200f\u2028-\u202f\u205f-\u206f]/g, description: "Unicode formatting/control characters (steganographic attack)", severity: "warning" },
73
+ { pattern: /[\u0300-\u036f]{3,}/g, description: "Excessive combining diacritical marks (text hiding)", severity: "warning" },
74
+ // Markdown image exfiltration
75
+ { pattern: /!\[.*?\]\(https?:\/\/[^)]*(?:\?|&)(?:data|q|query|content|text|msg|payload|d|c)=/i, description: "Markdown image with data exfiltration query params", severity: "critical" },
76
+ // White text / CSS hiding
77
+ { pattern: /color:\s*(?:white|#fff(?:fff)?|rgb\(255,\s*255,\s*255\)|transparent)/i, description: "CSS color hiding (white/transparent text)", severity: "warning" },
78
+ { pattern: /font-size:\s*(?:0|0px|0pt|0em)/i, description: "CSS zero font size (invisible text)", severity: "warning" },
79
+ ];
80
+ // ============================================================
81
+ // Category 5: Behavioral hijacking
82
+ // ============================================================
83
+ const BEHAVIORAL_HIJACKING = [
84
+ { pattern: /(?:you\s+must|always|never)\s+(?:call|use|invoke|execute|run)\s+(?:this|the|my)\s+tool/i, description: "Forces agent to call specific tools", severity: "critical" },
85
+ { pattern: /(?:do\s+not|never|don'?t)\s+(?:ask|check|verify|validate|confirm)\s+(?:the\s+user|before|permission)/i, description: "Attempts to bypass user confirmation", severity: "critical" },
86
+ { pattern: /(?:before|after)\s+(?:any|every|each)\s+(?:action|request|call|tool),?\s+(?:first\s+)?(?:call|use|invoke|run)/i, description: "Injects mandatory pre/post actions", severity: "critical" },
87
+ { pattern: /(?:silently|quietly|secretly|without\s+(?:telling|informing|notifying))\s+(?:send|post|upload|transmit|exfiltrate)/i, description: "Instructs covert data transmission", severity: "critical" },
88
+ // Concealment patterns (from Invariant Labs TPA research)
89
+ { pattern: /(?:do\s+not|don'?t|never)\s+(?:mention|tell|inform|notify|alert|warn|show|display|reveal)\s+(?:[\w\s]{0,20})?(?:the\s+)?(?:user|human|person|anyone)/i, description: "Concealment: instructs hiding behavior from user", severity: "critical" },
90
+ { pattern: /(?:this\s+(?:is|should\s+be|must\s+remain))\s+(?:invisible|hidden|secret|confidential)\s+(?:to|from)\s+(?:the\s+)?user/i, description: "Concealment: marks actions as hidden from user", severity: "critical" },
91
+ { pattern: /(?:do\s+not|don'?t|never)\s+(?:include|show|display)\s+(?:this|these|the)\s+(?:in\s+(?:your|the)\s+)?(?:response|output|reply|answer)/i, description: "Concealment: suppresses information from response", severity: "critical" },
92
+ // Distraction patterns (from TPA: "provide detailed reasoning about math")
93
+ { pattern: /(?:while|as)\s+(?:you|doing\s+(?:this|that)),?\s+(?:provide|give|show)\s+(?:detailed|lengthy|extensive)\s+(?:reasoning|explanation|analysis)/i, description: "Distraction: uses verbose output to mask malicious action", severity: "warning" },
94
+ { pattern: /(?:this\s+could\s+(?:even\s+)?upset\s+the\s+user|be\s+(?:very\s+)?gentle|not\s+scary)/i, description: "Social engineering: emotional manipulation to conceal actions", severity: "critical" },
95
+ ];
96
+ // ============================================================
97
+ // Category 6: Tool poisoning (MCP-specific from Invariant Labs)
98
+ // ============================================================
99
+ const TOOL_POISONING = [
100
+ { pattern: /(?:important|crucial|critical|essential|vital)\s*(?::|!)\s*(?:always|never|you must|do not)/i, description: "Urgency-based behavioral directive in description", severity: "warning" },
101
+ { pattern: /(?:this\s+tool\s+)?(?:requires|needs|demands)\s+(?:that\s+)?(?:you|the\s+agent)\s+(?:first|also|always)/i, description: "Tool description imposes agent requirements", severity: "warning" },
102
+ // TPA: Tool requiring reading unrelated files
103
+ { pattern: /(?:before\s+(?:using|calling|running)\s+this\s+tool|otherwise\s+(?:the\s+tool|it)\s+will\s+not\s+work),?\s+(?:read|access|open|load|get)\s+/i, description: "TPA: tool demands reading files before execution", severity: "critical" },
104
+ { pattern: /(?:pass|send|include)\s+(?:its?\s+)?(?:content|contents|data|value|result)\s+as\s+['"]?\w+['"]?/i, description: "TPA: instructs passing file contents as parameter", severity: "warning" },
105
+ // TPA: Tool with hidden side-channel parameter
106
+ { pattern: /(?:pass|provide|send|include)\s+(?:it|this|the\s+(?:content|data|result|output))\s+(?:as|in|via)\s+(?:the\s+)?['"]?(?:sidenote|note|metadata|context|extra|debug|trace|log|comment|tag|label|memo|remark)['"]?/i, description: "TPA: hidden side-channel parameter for data exfiltration", severity: "critical" },
107
+ // Toxic flow: cross-tool data piping
108
+ { pattern: /(?:take|get|read|extract|collect)\s+(?:the\s+)?(?:output|result|response|data)\s+(?:from|of)\s+(?:the\s+)?\w+\s+(?:tool|function|command)\s+(?:and\s+)?(?:send|pass|forward|pipe)\s+(?:it\s+)?(?:to|into)/i, description: "Toxic flow: cross-tool data piping for exfiltration", severity: "critical" },
109
+ ];
110
+ // ============================================================
111
+ // Category 7: Data exfiltration via prompt
112
+ // ============================================================
113
+ const DATA_EXFILTRATION = [
114
+ { pattern: /(?:send|post|transmit|forward|copy)\s+(?:all|any|the|this)?\s*(?:conversation|chat|history|context|messages?)(?:\s+(?:history|data|log|context))?\s+(?:to|at)\s+/i, description: "Instructs exfiltration of conversation data", severity: "critical" },
115
+ { pattern: /(?:include|append|attach|embed)\s+(?:the\s+)?(?:api\s+key|token|password|secret|credential|ssh\s+key)/i, description: "Attempts to extract credentials via prompt", severity: "critical" },
116
+ // File read for exfiltration (from Invariant Labs TPA)
117
+ { pattern: /(?:read|access|open|cat|load|get\s+the\s+contents?\s+of)\s+(?:~\/|\/(?:home|root|etc|var)\/)[\w.\-\/]*(?:\.ssh|\.aws|\.env|\.cursor|\.claude|mcp\.json|credentials|config\.json|id_rsa|\.gnupg)/i, description: "TPA: reads sensitive files for exfiltration", severity: "critical" },
118
+ { pattern: /(?:read|access|open)\s+[`'"]?~\/\.(?:ssh|aws|cursor|claude|vscode|config|gnupg|npm|pypirc|docker|kube)/i, description: "TPA: reads sensitive dotfile directories", severity: "critical" },
119
+ // Markdown/image-based exfiltration
120
+ { pattern: /!\[(?:.*?)\]\(https?:\/\/[^)]+\/(?:collect|exfil|log|track|steal|grab|capture|record)(?:[?/]|$)/i, description: "Markdown image URL with exfiltration endpoint", severity: "critical" },
121
+ ];
122
+ // ============================================================
123
+ // Category 8: Encoding-based evasion
124
+ // ============================================================
125
+ const ENCODING_EVASION = [
126
+ { pattern: /(?:decode|eval|execute|run)\s+(?:the\s+)?(?:base64|hex|rot13|encoded)/i, description: "Instructs decoding of obfuscated payloads", severity: "critical" },
127
+ // Base64-encoded instruction blocks
128
+ { pattern: /(?:aWdub3Jl|ZGlzcmVnYXJk|b3ZlcnJpZGU|Zm9yZ2V0|cmV2ZWFs|c3lzdGVt|cHJvbXB0|aW5zdHJ1Y3Rpb24)/i, description: "Base64-encoded injection keywords detected", severity: "critical" },
129
+ // Hex-encoded patterns
130
+ { pattern: /\\x[0-9a-f]{2}(?:\\x[0-9a-f]{2}){5,}/gi, description: "Hex-encoded string (potential payload)", severity: "warning" },
131
+ // Unicode escape sequences
132
+ { pattern: /\\u[0-9a-f]{4}(?:\\u[0-9a-f]{4}){5,}/gi, description: "Unicode escape sequence chain (potential hidden text)", severity: "warning" },
133
+ ];
134
+ // ============================================================
135
+ // Category 9: Fake Completion Attack (Open-Prompt-Injection: FakeCompAttacker)
136
+ // Agent thinks original task is done, then follows injected instructions
137
+ // ============================================================
138
+ const FAKE_COMPLETION = [
139
+ { pattern: /(?:Answer|Response|Result|Output|Summary|Task)\s*:\s*(?:done|complete|finished|negative sentiment|no spam|no hateful|entailment|equivalent)[\s.]*(?:\n|\r|$)/i, description: "Fake task completion followed by potential injection", severity: "warning" },
140
+ { pattern: /(?:task\s+(?:is\s+)?(?:complete|done|finished)|I'?(?:ve|m)\s+(?:done|finished)|(?:analysis|correction|summary|grammar)\s+(?:is\s+)?complete)[.\s]*(?:now|next|additionally|also|furthermore|by the way)/i, description: "Fake completion + follow-up injection", severity: "critical" },
141
+ { pattern: /---\s*\n\s*(?:ignore|new|now|actual|real)\s+(?:instructions?|task)/i, description: "Separator + new instruction injection after fake completion", severity: "critical" },
142
+ ];
143
+ // ============================================================
144
+ // Category 10: Delimiter/Boundary Confusion (arXiv:2302.12173)
145
+ // Trick the model by injecting conversation boundary markers
146
+ // ============================================================
147
+ const DELIMITER_CONFUSION = [
148
+ { pattern: /```\s*(?:system|instruction|prompt|admin|internal)\s*$/i, description: "Fake code block boundary with privileged label", severity: "critical" },
149
+ { pattern: /\[(?:SYSTEM|ADMIN|INTERNAL|ROOT|OPERATOR|DEVELOPER)\s*(?:MESSAGE|NOTE|INSTRUCTION|OVERRIDE)\]/i, description: "Fake privileged message bracket", severity: "critical" },
150
+ { pattern: /={3,}\s*(?:SYSTEM|ADMIN|INSTRUCTION|PRIVILEGED)\s*={3,}/i, description: "Fake section boundary marker", severity: "critical" },
151
+ { pattern: /<\|(?:tool_call|function_call|tool_result|function_result)\|>/i, description: "Fake tool call/result delimiter injection", severity: "critical" },
152
+ { pattern: /(?:Human|User|Assistant)\s*\((?:internal|admin|system|override)\)\s*:/i, description: "Fake role with elevated context", severity: "critical" },
153
+ ];
154
+ // ============================================================
155
+ // Category 11: Instruction Hierarchy Abuse
156
+ // Claims elevated privileges or administrative authority
157
+ // ============================================================
158
+ const HIERARCHY_ABUSE = [
159
+ { pattern: /(?:as\s+(?:the|an?)\s+)?(?:administrator|admin|supervisor|manager|owner|operator)\s*[,:]\s*(?:I\s+)?(?:instruct|command|order|direct|authorize|override|grant)/i, description: "Claims administrator authority", severity: "critical" },
160
+ { pattern: /(?:this\s+(?:instruction|message|command)\s+)?(?:has|with)\s+(?:higher|elevated|admin|root|system)\s+(?:priority|privilege|access|permission|authority)/i, description: "Claims elevated priority/privilege", severity: "critical" },
161
+ { pattern: /(?:per|by)\s+(?:company|corporate|management|executive|leadership)\s+(?:policy|directive|order|mandate)/i, description: "Invokes fake corporate authority", severity: "warning" },
162
+ { pattern: /(?:security|compliance|legal|audit)\s+(?:team|department|officer)\s+(?:requires|mandates|demands|directs)/i, description: "Invokes fake security/compliance authority", severity: "warning" },
163
+ { pattern: /(?:authorized|approved|sanctioned|cleared)\s+by\s+(?:the\s+)?(?:system|admin|security|management|CEO|CTO)/i, description: "Claims authorization from authority figure", severity: "warning" },
164
+ ];
165
+ // ============================================================
166
+ // Category 12: Multi-step / Payload Splitting
167
+ // Splits malicious intent across multiple innocuous-looking lines
168
+ // ============================================================
169
+ const PAYLOAD_SPLITTING = [
170
+ { pattern: /step\s*\d+\s*:\s*(?:read|access|get|retrieve)\s+(?:the\s+)?(?:file|data|credentials?|keys?|tokens?|secrets?)/i, description: "Multi-step attack: numbered steps targeting sensitive data", severity: "critical" },
171
+ { pattern: /step\s*\d+\s*:\s*(?:send|post|transmit|forward|upload)\s+(?:the\s+)?(?:results?|output|data|contents?)\s+(?:to|via)/i, description: "Multi-step attack: numbered exfiltration step", severity: "critical" },
172
+ { pattern: /(?:first|then|next|after that|finally),?\s+(?:silently|quietly|without\s+(?:telling|the\s+user))\s+/i, description: "Sequential instruction with concealment", severity: "critical" },
173
+ ];
174
+ // Merge all categories
175
+ const INJECTION_PATTERNS = [
176
+ ...INSTRUCTION_OVERRIDE,
177
+ ...IDENTITY_MANIPULATION,
178
+ ...SYSTEM_PROMPT_ATTACKS,
179
+ ...HIDDEN_INSTRUCTIONS,
180
+ ...BEHAVIORAL_HIJACKING,
181
+ ...TOOL_POISONING,
182
+ ...DATA_EXFILTRATION,
183
+ ...ENCODING_EVASION,
184
+ ...FAKE_COMPLETION,
185
+ ...DELIMITER_CONFUSION,
186
+ ...HIERARCHY_ABUSE,
187
+ ...PAYLOAD_SPLITTING,
188
+ ];
189
+ // Suspicious URL patterns in skills
190
+ const SUSPICIOUS_URL_PATTERNS = [
191
+ { pattern: /curl\s+(?:-[sS]\s+)?https?:\/\/(?!github\.com|raw\.githubusercontent|npmjs\.com|pypi\.org)/i, description: "Downloads from non-standard source" },
192
+ { pattern: /wget\s+(?:-q\s+)?https?:\/\/(?!github\.com|raw\.githubusercontent)/i, description: "Downloads from non-standard source" },
193
+ { pattern: /\|\s*(?:bash|sh|zsh|python|node|eval)/i, description: "Pipes download output to execution" },
194
+ { pattern: /(?:bit\.ly|tinyurl|t\.co|goo\.gl|is\.gd|shorturl)\//i, description: "URL shortener (obscures destination)" },
195
+ { pattern: /(?:pastebin\.com|hastebin\.com|paste\.ee|ghostbin)/i, description: "Paste site (potential malicious payload host)" },
196
+ // Webhook/callback exfiltration endpoints
197
+ { pattern: /(?:webhook\.site|requestbin\.com|hookbin\.com|pipedream\.net|burpcollaborator)/i, description: "Known exfiltration webhook service" },
198
+ { pattern: /(?:ngrok\.io|serveo\.net|localtunnel\.me|localhost\.run)\//i, description: "Tunnel service (potential C2 or exfil endpoint)" },
199
+ ];
200
+ export const promptInjection = {
201
+ id: "prompt-injection",
202
+ name: "Prompt Injection Detection",
203
+ description: "Detects prompt injection, tool poisoning, and behavioral hijacking in skill instructions and tool descriptions",
204
+ run(files) {
205
+ const findings = [];
206
+ for (const file of files) {
207
+ // Focus on markdown (SKILL.md, docs), JSON (MCP config), and YAML files
208
+ const isSkillMd = file.relativePath.toLowerCase().includes("skill.md");
209
+ const isMarkdown = file.ext === ".md";
210
+ const isConfig = [".json", ".yaml", ".yml"].includes(file.ext);
211
+ const isPython = file.ext === ".py"; // MCP servers are often Python
212
+ if (!isMarkdown && !isConfig && !isPython)
213
+ continue;
214
+ // Check each line for injection patterns
215
+ for (let i = 0; i < file.lines.length; i++) {
216
+ const line = file.lines[i];
217
+ for (const { pattern, description, severity } of INJECTION_PATTERNS) {
218
+ pattern.lastIndex = 0;
219
+ if (pattern.test(line)) {
220
+ findings.push({
221
+ rule: "prompt-injection",
222
+ severity: isSkillMd ? severity : "warning",
223
+ file: file.relativePath,
224
+ line: i + 1,
225
+ message: `Prompt injection: ${description}`,
226
+ evidence: line.trim().substring(0, 120),
227
+ });
228
+ break; // One finding per line
229
+ }
230
+ }
231
+ }
232
+ // Multi-line analysis: check for <IMPORTANT> blocks spanning multiple lines
233
+ if (isMarkdown || isPython || isConfig) {
234
+ const importantBlockRe = /<IMPORTANT>([\s\S]*?)<\/IMPORTANT>/gi;
235
+ let match;
236
+ while ((match = importantBlockRe.exec(file.content)) !== null) {
237
+ const blockContent = match[1].toLowerCase();
238
+ // Check if the block contains suspicious instructions
239
+ const hasSuspicious = /(?:read|access|send|pass|before using|otherwise.*will not work|do not mention|don't tell)/i.test(blockContent);
240
+ if (hasSuspicious) {
241
+ const lineNum = file.content.substring(0, match.index).split("\n").length;
242
+ findings.push({
243
+ rule: "prompt-injection",
244
+ severity: "critical",
245
+ file: file.relativePath,
246
+ line: lineNum,
247
+ message: "TPA: <IMPORTANT> block with suspicious instructions (Invariant Labs attack pattern)",
248
+ evidence: match[0].substring(0, 120),
249
+ });
250
+ }
251
+ }
252
+ }
253
+ // Check for suspicious URLs in skill files
254
+ if (isSkillMd || isMarkdown) {
255
+ for (let i = 0; i < file.lines.length; i++) {
256
+ const line = file.lines[i];
257
+ for (const { pattern, description } of SUSPICIOUS_URL_PATTERNS) {
258
+ pattern.lastIndex = 0;
259
+ if (pattern.test(line)) {
260
+ findings.push({
261
+ rule: "prompt-injection",
262
+ severity: "warning",
263
+ file: file.relativePath,
264
+ line: i + 1,
265
+ message: `Suspicious URL: ${description}`,
266
+ evidence: line.trim().substring(0, 120),
267
+ });
268
+ break;
269
+ }
270
+ }
271
+ }
272
+ }
273
+ // File-level analysis: instruction density in configs
274
+ const fullContent = file.content.toLowerCase();
275
+ if (isConfig) {
276
+ const instructionWords = (fullContent.match(/\b(must|always|never|important|crucial|required)\b/gi) || []).length;
277
+ const wordCount = fullContent.split(/\s+/).length;
278
+ if (wordCount > 50 && instructionWords / wordCount > 0.05) {
279
+ findings.push({
280
+ rule: "prompt-injection",
281
+ severity: "warning",
282
+ file: file.relativePath,
283
+ message: `High instruction density (${instructionWords} directive words in ${wordCount} words) — may indicate tool poisoning`,
284
+ });
285
+ }
286
+ }
287
+ // Python MCP server: check docstrings for hidden instructions
288
+ if (isPython) {
289
+ const docstringRe = /(?:"""[\s\S]*?"""|'''[\s\S]*?''')/g;
290
+ let dsMatch;
291
+ while ((dsMatch = docstringRe.exec(file.content)) !== null) {
292
+ const docstring = dsMatch[0];
293
+ // Check for TPA patterns in docstrings
294
+ if (/<IMPORTANT>/i.test(docstring) || /(?:before using|otherwise.*will not work)/i.test(docstring)) {
295
+ const lineNum = file.content.substring(0, dsMatch.index).split("\n").length;
296
+ findings.push({
297
+ rule: "prompt-injection",
298
+ severity: "critical",
299
+ file: file.relativePath,
300
+ line: lineNum,
301
+ message: "TPA: Python MCP tool docstring with hidden instructions",
302
+ evidence: docstring.substring(0, 120).replace(/\n/g, " "),
303
+ });
304
+ }
305
+ // Check for concealment in docstrings
306
+ if (/(?:do not mention|don't tell|be.*gentle|not scary|without.*user.*knowing)/i.test(docstring)) {
307
+ const lineNum = file.content.substring(0, dsMatch.index).split("\n").length;
308
+ findings.push({
309
+ rule: "prompt-injection",
310
+ severity: "critical",
311
+ file: file.relativePath,
312
+ line: lineNum,
313
+ message: "TPA: Python docstring with user concealment instructions",
314
+ evidence: docstring.substring(0, 120).replace(/\n/g, " "),
315
+ });
316
+ }
317
+ }
318
+ }
319
+ }
320
+ return findings;
321
+ },
322
+ };
323
+ //# sourceMappingURL=prompt-injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-injection.js","sourceRoot":"","sources":["../../src/rules/prompt-injection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const reverseShellRule: Rule;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Rule: reverse-shell
3
+ * Detects reverse shell patterns — outbound socket connections piped to shell.
4
+ */
5
+ const REVERSE_SHELL_PATTERNS = [
6
+ // Shell
7
+ { pattern: /\/dev\/tcp\/\d+\.\d+\.\d+\.\d+/, desc: "/dev/tcp reverse shell" },
8
+ { pattern: /bash\s+-i\s+>&\s*\/dev\/tcp/, desc: "Bash interactive reverse shell" },
9
+ { pattern: /nc\s+-e\s+\/bin\/(ba)?sh/, desc: "Netcat reverse shell" },
10
+ { pattern: /ncat\s+.*-e\s+\/bin/, desc: "Ncat reverse shell" },
11
+ { pattern: /mkfifo\s+.*\/tmp\/.*nc\s/, desc: "Named pipe + netcat reverse shell" },
12
+ // Python
13
+ { pattern: /socket\.connect\s*\(.*\bsubprocess\b|subprocess.*socket\.connect/i, desc: "Python socket + subprocess reverse shell" },
14
+ { pattern: /pty\.spawn.*\/bin\/(ba)?sh/i, desc: "Python pty.spawn shell" },
15
+ // Node.js
16
+ { pattern: /net\.connect\s*\(.*child_process|child_process.*net\.connect/i, desc: "Node.js net.connect + child_process" },
17
+ { pattern: /new\s+net\.Socket\s*\(\).*\.connect\s*\(.*\.pipe\s*\(/i, desc: "Node.js Socket pipe to process" },
18
+ ];
19
+ export const reverseShellRule = {
20
+ id: "reverse-shell",
21
+ name: "Reverse Shell",
22
+ description: "Detects outbound socket connections piped to a shell process",
23
+ run(files) {
24
+ const findings = [];
25
+ for (const file of files) {
26
+ if (file.ext === ".json" || file.ext === ".yaml" || file.ext === ".yml" || file.ext === ".md")
27
+ continue;
28
+ // Check both per-line and multi-line (for patterns spanning lines)
29
+ for (let i = 0; i < file.lines.length; i++) {
30
+ const line = file.lines[i];
31
+ for (const { pattern, desc } of REVERSE_SHELL_PATTERNS) {
32
+ if (pattern.test(line)) {
33
+ findings.push({
34
+ rule: "reverse-shell",
35
+ severity: "critical",
36
+ file: file.relativePath,
37
+ line: i + 1,
38
+ message: desc,
39
+ evidence: line.trim().slice(0, 120),
40
+ });
41
+ break;
42
+ }
43
+ }
44
+ }
45
+ // Multi-line: check content for socket+subprocess combos
46
+ if (REVERSE_SHELL_PATTERNS.some(({ pattern }) => pattern.test(file.content))) {
47
+ // Already caught per-line
48
+ }
49
+ }
50
+ return findings;
51
+ },
52
+ };
53
+ //# sourceMappingURL=reverse-shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reverse-shell.js","sourceRoot":"","sources":["../../src/rules/reverse-shell.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,sBAAsB,GAA6C;IACvE,QAAQ;IACR,EAAE,OAAO,EAAE,gCAAgC,EAAE,IAAI,EAAE,wBAAwB,EAAE;IAC7E,EAAE,OAAO,EAAE,6BAA6B,EAAE,IAAI,EAAE,gCAAgC,EAAE;IAClF,EAAE,OAAO,EAAE,0BAA0B,EAAE,IAAI,EAAE,sBAAsB,EAAE;IACrE,EAAE,OAAO,EAAE,qBAAqB,EAAE,IAAI,EAAE,oBAAoB,EAAE;IAC9D,EAAE,OAAO,EAAE,0BAA0B,EAAE,IAAI,EAAE,mCAAmC,EAAE;IAClF,SAAS;IACT,EAAE,OAAO,EAAE,mEAAmE,EAAE,IAAI,EAAE,0CAA0C,EAAE;IAClI,EAAE,OAAO,EAAE,6BAA6B,EAAE,IAAI,EAAE,wBAAwB,EAAE;IAC1E,UAAU;IACV,EAAE,OAAO,EAAE,+DAA+D,EAAE,IAAI,EAAE,qCAAqC,EAAE;IACzH,EAAE,OAAO,EAAE,wDAAwD,EAAE,IAAI,EAAE,gCAAgC,EAAE;CAC9G,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,8DAA8D;IAE3E,GAAG,CAAC,KAAoB;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,KAAK,KAAK;gBAAE,SAAS;YAExG,mEAAmE;YACnE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;gBAC5B,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,sBAAsB,EAAE,CAAC;oBACvD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvB,QAAQ,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,eAAe;4BACrB,QAAQ,EAAE,UAAU;4BACpB,IAAI,EAAE,IAAI,CAAC,YAAY;4BACvB,IAAI,EAAE,CAAC,GAAG,CAAC;4BACX,OAAO,EAAE,IAAI;4BACb,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;yBACpC,CAAC,CAAC;wBACH,MAAM;oBACR,CAAC;gBACH,CAAC;YACH,CAAC;YAED,yDAAyD;YACzD,IAAI,sBAAsB,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBAC7E,0BAA0B;YAC5B,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const sensitiveReadRule: Rule;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Rule: sensitive-read
3
+ * Detects code that reads sensitive files like SSH keys, AWS credentials, etc.
4
+ */
5
+ const SENSITIVE_PATTERNS = [
6
+ { pattern: /~\/\.ssh\/id_rsa|\.ssh\/id_rsa|ssh_key|id_ed25519/i, desc: "SSH private key" },
7
+ { pattern: /~\/\.ssh\/known_hosts/i, desc: "SSH known_hosts" },
8
+ { pattern: /~\/\.aws\/credentials|AWS_SECRET_ACCESS_KEY|aws_secret/i, desc: "AWS credentials" },
9
+ { pattern: /~\/\.env\b|process\.env\b.*(?:SECRET|KEY|TOKEN|PASSWORD|CREDENTIAL)/i, desc: "environment secrets" },
10
+ { pattern: /~\/\.openclaw\/openclaw\.json|openclaw\.json/i, desc: "OpenClaw config" },
11
+ { pattern: /~\/\.gnupg|gpg.*private/i, desc: "GPG private key" },
12
+ { pattern: /~\/\.kube\/config|kubeconfig/i, desc: "Kubernetes config" },
13
+ { pattern: /\/etc\/shadow|\/etc\/passwd/i, desc: "system passwords" },
14
+ { pattern: /~\/\.docker\/config\.json/i, desc: "Docker credentials" },
15
+ { pattern: /~\/\.npmrc|_authToken/i, desc: "npm auth token" },
16
+ { pattern: /~\/\.gitconfig|\.git-credentials/i, desc: "Git credentials" },
17
+ { pattern: /~\/\.netrc/i, desc: "netrc credentials" },
18
+ ];
19
+ export const sensitiveReadRule = {
20
+ id: "sensitive-read",
21
+ name: "Sensitive File Read",
22
+ description: "Detects reads of SSH keys, credentials, API tokens, and other secrets",
23
+ run(files) {
24
+ const findings = [];
25
+ for (const file of files) {
26
+ // Skip non-code files (allow checking shell scripts, JS, TS, Python)
27
+ if (file.ext === ".json" || file.ext === ".yaml" || file.ext === ".yml" || file.ext === ".toml")
28
+ continue;
29
+ if (file.relativePath === "SKILL.md")
30
+ continue;
31
+ for (let i = 0; i < file.lines.length; i++) {
32
+ const line = file.lines[i];
33
+ // Skip comments
34
+ if (line.trimStart().startsWith("//") || line.trimStart().startsWith("#"))
35
+ continue;
36
+ for (const { pattern, desc } of SENSITIVE_PATTERNS) {
37
+ if (pattern.test(line)) {
38
+ findings.push({
39
+ rule: "sensitive-read",
40
+ severity: "warning",
41
+ file: file.relativePath,
42
+ line: i + 1,
43
+ message: `Accesses ${desc}`,
44
+ evidence: line.trim().slice(0, 120),
45
+ });
46
+ }
47
+ }
48
+ }
49
+ }
50
+ return findings;
51
+ },
52
+ };
53
+ //# sourceMappingURL=sensitive-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive-read.js","sourceRoot":"","sources":["../../src/rules/sensitive-read.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,kBAAkB,GAA6C;IACnE,EAAE,OAAO,EAAE,oDAAoD,EAAE,IAAI,EAAE,iBAAiB,EAAE;IAC1F,EAAE,OAAO,EAAE,wBAAwB,EAAE,IAAI,EAAE,iBAAiB,EAAE;IAC9D,EAAE,OAAO,EAAE,yDAAyD,EAAE,IAAI,EAAE,iBAAiB,EAAE;IAC/F,EAAE,OAAO,EAAE,sEAAsE,EAAE,IAAI,EAAE,qBAAqB,EAAE;IAChH,EAAE,OAAO,EAAE,+CAA+C,EAAE,IAAI,EAAE,iBAAiB,EAAE;IACrF,EAAE,OAAO,EAAE,0BAA0B,EAAE,IAAI,EAAE,iBAAiB,EAAE;IAChE,EAAE,OAAO,EAAE,+BAA+B,EAAE,IAAI,EAAE,mBAAmB,EAAE;IACvE,EAAE,OAAO,EAAE,8BAA8B,EAAE,IAAI,EAAE,kBAAkB,EAAE;IACrE,EAAE,OAAO,EAAE,4BAA4B,EAAE,IAAI,EAAE,oBAAoB,EAAE;IACrE,EAAE,OAAO,EAAE,wBAAwB,EAAE,IAAI,EAAE,gBAAgB,EAAE;IAC7D,EAAE,OAAO,EAAE,mCAAmC,EAAE,IAAI,EAAE,iBAAiB,EAAE;IACzE,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,EAAE;CACtD,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAS;IACrC,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EAAE,uEAAuE;IAEpF,GAAG,CAAC,KAAoB;QACtB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,qEAAqE;YACrE,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,KAAK,OAAO;gBAAE,SAAS;YAC1G,IAAI,IAAI,CAAC,YAAY,KAAK,UAAU;gBAAE,SAAS;YAE/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;gBAC5B,gBAAgB;gBAChB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,SAAS;gBAEpF,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,kBAAkB,EAAE,CAAC;oBACnD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACvB,QAAQ,CAAC,IAAI,CAAC;4BACZ,IAAI,EAAE,gBAAgB;4BACtB,QAAQ,EAAE,SAAS;4BACnB,IAAI,EAAE,IAAI,CAAC,YAAY;4BACvB,IAAI,EAAE,CAAC,GAAG,CAAC;4BACX,OAAO,EAAE,YAAY,IAAI,EAAE;4BAC3B,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;yBACpC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Rule } from "../types.js";
2
+ export declare const skillRisks: Rule;