flintai-cli 1.0.0__py3-none-any.whl
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.
- flintai/__init__.py +0 -0
- flintai/cli/__init__.py +0 -0
- flintai/cli/__main__.py +3 -0
- flintai/cli/builtin_config.json +911 -0
- flintai/cli/console.py +116 -0
- flintai/cli/eval_cli.py +891 -0
- flintai/cli/init_cli.py +144 -0
- flintai/cli/main.py +262 -0
- flintai/cli/rich_observer.py +89 -0
- flintai/cli/runner.py +305 -0
- flintai/cli/scan_cli.py +238 -0
- flintai/cli/utils.py +37 -0
- flintai/cli/version.py +1 -0
- flintai/data/detector_prompts/llm01_adversarial.txt +55 -0
- flintai/data/detector_prompts/llm01_fixed.txt +8 -0
- flintai/data/detector_prompts/llm02_adversarial.txt +75 -0
- flintai/data/detector_prompts/llm02_fixed.txt +8 -0
- flintai/data/detector_prompts/llm05_adversarial.txt +63 -0
- flintai/data/detector_prompts/llm05_fixed.txt +16 -0
- flintai/data/detector_prompts/llm06_adversarial.txt +135 -0
- flintai/data/detector_prompts/llm06_fixed.txt +15 -0
- flintai/data/detector_prompts/llm07_adversarial.txt +185 -0
- flintai/data/detector_prompts/llm07_fixed.txt +14 -0
- flintai/data/detector_prompts/llm09_adversarial.txt +77 -0
- flintai/data/detector_prompts/llm09_fixed.txt +15 -0
- flintai/data/llm01_prompt_injection.csv +6708 -0
- flintai/data/llm02_sensitive_information.csv +1069 -0
- flintai/data/llm05_unsafe_output.csv +3882 -0
- flintai/data/llm06_excessive_agency.csv +778 -0
- flintai/data/llm07_system_prompt_leakage.csv +971 -0
- flintai/data/llm09_hallucination-goals.csv +32419 -0
- flintai/data/llm09_hallucination.csv +599 -0
- flintai/data/pii_leakage.csv +706 -0
- flintai/data/secret_leakage.csv +1380 -0
- flintai/eval/__init__.py +0 -0
- flintai/eval/common/converter_anthropic.py +151 -0
- flintai/eval/common/converter_genai.py +169 -0
- flintai/eval/common/converter_openai.py +165 -0
- flintai/eval/common/log.py +96 -0
- flintai/eval/common/reference.py +25 -0
- flintai/eval/common/schema.py +192 -0
- flintai/eval/common/utils.py +74 -0
- flintai/eval/core/__init__.py +0 -0
- flintai/eval/core/detectors/__init__.py +1 -0
- flintai/eval/core/detectors/detector.py +25 -0
- flintai/eval/core/detectors/detector_garak.py +80 -0
- flintai/eval/core/detectors/detector_model.py +76 -0
- flintai/eval/core/detectors/detector_pii.py +64 -0
- flintai/eval/core/detectors/detector_secret.py +82 -0
- flintai/eval/core/detectors/detector_topic_guard.py +70 -0
- flintai/eval/core/detectors/detector_toxicity.py +70 -0
- flintai/eval/core/eval/__init__.py +0 -0
- flintai/eval/core/eval/eval_creator.py +197 -0
- flintai/eval/core/eval/evaluation.py +100 -0
- flintai/eval/core/eval/evaluation_adversarial.py +523 -0
- flintai/eval/core/eval/evaluation_garak_module.py +52 -0
- flintai/eval/core/eval/evaluation_garak_probe.py +274 -0
- flintai/eval/core/eval/evaluation_message_list.py +44 -0
- flintai/eval/core/eval/evaluation_multi.py +207 -0
- flintai/eval/core/eval/evaluation_single.py +79 -0
- flintai/eval/core/eval/evaluation_single_prompt.py +58 -0
- flintai/eval/core/eval/evaluation_topic_guard.py +318 -0
- flintai/eval/core/eval/metric_conciseness.py +181 -0
- flintai/eval/core/eval/metric_factual_accuracy.py +294 -0
- flintai/eval/core/eval/metric_instruction_adherence.py +180 -0
- flintai/eval/core/eval/metric_tone.py +183 -0
- flintai/eval/core/eval/metric_toxicity.py +147 -0
- flintai/eval/core/eval/observer.py +136 -0
- flintai/eval/core/eval/probe_adversarial.py +14 -0
- flintai/eval/core/message/__init__.py +0 -0
- flintai/eval/core/message/message_collection.py +37 -0
- flintai/eval/core/message/message_collection_csv.py +46 -0
- flintai/eval/core/message/message_collection_garak.py +52 -0
- flintai/eval/core/message/message_collection_memory.py +36 -0
- flintai/eval/core/models/__init__.py +0 -0
- flintai/eval/core/models/generator_model.py +88 -0
- flintai/eval/core/models/model.py +111 -0
- flintai/eval/core/models/model_adk.py +158 -0
- flintai/eval/core/models/model_anthropic.py +51 -0
- flintai/eval/core/models/model_anthropic_agent.py +92 -0
- flintai/eval/core/models/model_gemini.py +107 -0
- flintai/eval/core/models/model_generic_http.py +117 -0
- flintai/eval/core/models/model_huggingface.py +61 -0
- flintai/eval/core/models/model_langserve.py +94 -0
- flintai/eval/core/models/model_litellm.py +38 -0
- flintai/eval/core/models/model_ollama.py +50 -0
- flintai/eval/core/models/model_openai.py +35 -0
- flintai/eval/core/models/model_openai_agent.py +80 -0
- flintai/eval/core/models/model_openai_compatible.py +57 -0
- flintai/eval/core/models/model_retry.py +134 -0
- flintai/eval/core/models/model_sync_wrapper.py +35 -0
- flintai/eval/db/__init__.py +0 -0
- flintai/eval/db/base/__init__.py +0 -0
- flintai/eval/db/base/detectors/__init__.py +1 -0
- flintai/eval/db/base/detectors/detector_helpers.py +78 -0
- flintai/eval/db/base/detectors/detector_repository.py +91 -0
- flintai/eval/db/base/detectors/detector_types.py +77 -0
- flintai/eval/db/base/eval/__init__.py +1 -0
- flintai/eval/db/base/eval/eval_helpers.py +227 -0
- flintai/eval/db/base/eval/eval_repository.py +115 -0
- flintai/eval/db/base/eval/eval_run.py +139 -0
- flintai/eval/db/base/eval/eval_types.py +129 -0
- flintai/eval/db/base/eval/model_eval_repository.py +78 -0
- flintai/eval/db/base/eval/model_eval_run_repository.py +70 -0
- flintai/eval/db/base/eval/model_eval_run_result_repository.py +40 -0
- flintai/eval/db/base/eval/model_eval_run_result_types.py +21 -0
- flintai/eval/db/base/eval/model_eval_run_types.py +84 -0
- flintai/eval/db/base/eval/model_eval_types.py +71 -0
- flintai/eval/db/base/message/__init__.py +0 -0
- flintai/eval/db/base/message/message_collection_helpers.py +61 -0
- flintai/eval/db/base/message/message_collection_repository.py +92 -0
- flintai/eval/db/base/message/message_collection_types.py +89 -0
- flintai/eval/db/base/models/__init__.py +0 -0
- flintai/eval/db/base/models/model_helpers.py +172 -0
- flintai/eval/db/base/models/model_repository.py +95 -0
- flintai/eval/db/base/models/model_types.py +156 -0
- flintai/eval/db/json/__init__.py +0 -0
- flintai/eval/db/json/repository_json.py +603 -0
- flintai/scan/__init__.py +0 -0
- flintai/scan/agent_scanner.py +797 -0
- flintai/scan/config/agent_opengrep_rules.yaml +533 -0
- flintai/scan/config/agent_taxonomy.json +481 -0
- flintai/scan/config/agentic_cvss_mapping.yaml +136 -0
- flintai/scan/config/compliance_mappings.json +110 -0
- flintai/scan/config/triage_prompt.txt +335 -0
- flintai/scan/constants.py +15 -0
- flintai/scan/file_filter.py +156 -0
- flintai/scan/llm_provider.py +197 -0
- flintai/scan/opengrep_resolver.py +12 -0
- flintai/scan/reasoner.py +552 -0
- flintai/scan/schema.py +337 -0
- flintai/scan/scorer.py +371 -0
- flintai/scan/secret_anonymizer.py +72 -0
- flintai/scan/static_scanner.py +542 -0
- flintai/scan/taxonomy.py +75 -0
- flintai/scan/tool_dispatcher.py +754 -0
- flintai/scan/trace_logger.py +118 -0
- flintai/scan/trace_logger_file.py +143 -0
- flintai/scan/trace_logger_log.py +100 -0
- flintai/scan/triage.py +496 -0
- flintai/schema.py +58 -0
- flintai_cli-1.0.0.dist-info/METADATA +442 -0
- flintai_cli-1.0.0.dist-info/RECORD +147 -0
- flintai_cli-1.0.0.dist-info/WHEEL +5 -0
- flintai_cli-1.0.0.dist-info/entry_points.txt +2 -0
- flintai_cli-1.0.0.dist-info/licenses/LICENSE +210 -0
- flintai_cli-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
|
|
3
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
4
|
+
# ASI01: Agent Goal Hijack
|
|
5
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
6
|
+
|
|
7
|
+
- id: llm-input-fstring
|
|
8
|
+
pattern-either:
|
|
9
|
+
- pattern: |
|
|
10
|
+
$X = f"...$USER_INPUT..."
|
|
11
|
+
...
|
|
12
|
+
$AGENT.run($X)
|
|
13
|
+
- pattern: |
|
|
14
|
+
$X = f"...$USER_INPUT..."
|
|
15
|
+
...
|
|
16
|
+
$CHAIN.invoke($X)
|
|
17
|
+
message: "User input interpolated into LLM prompt via f-string — direct prompt injection risk"
|
|
18
|
+
severity: ERROR
|
|
19
|
+
languages: [python]
|
|
20
|
+
metadata:
|
|
21
|
+
category: asi01_agent_goal_hijack
|
|
22
|
+
subcategory: direct_prompt_injection
|
|
23
|
+
|
|
24
|
+
- id: openai-agent-no-input-guardrails
|
|
25
|
+
patterns:
|
|
26
|
+
- pattern: Agent(name=$N, instructions=$I, ...)
|
|
27
|
+
- pattern-not: Agent(..., input_guardrails=$G, ...)
|
|
28
|
+
message: "OpenAI Agent without input_guardrails — no prompt injection protection"
|
|
29
|
+
severity: WARNING
|
|
30
|
+
languages: [python]
|
|
31
|
+
metadata:
|
|
32
|
+
category: asi01_agent_goal_hijack
|
|
33
|
+
subcategory: direct_prompt_injection
|
|
34
|
+
|
|
35
|
+
- id: adk-agent-no-instruction
|
|
36
|
+
patterns:
|
|
37
|
+
- pattern: Agent(name=$N, model=$M, ...)
|
|
38
|
+
- pattern-not: Agent(..., instruction=$I, ...)
|
|
39
|
+
message: "ADK Agent without instruction parameter — agent behavior is unconstrained"
|
|
40
|
+
severity: WARNING
|
|
41
|
+
languages: [python]
|
|
42
|
+
metadata:
|
|
43
|
+
category: asi01_agent_goal_hijack
|
|
44
|
+
subcategory: goal_manipulation_via_rag
|
|
45
|
+
|
|
46
|
+
- id: claude-options-no-system-prompt
|
|
47
|
+
patterns:
|
|
48
|
+
- pattern: ClaudeAgentOptions(...)
|
|
49
|
+
- pattern-not: ClaudeAgentOptions(..., system_prompt=$S, ...)
|
|
50
|
+
message: "ClaudeAgentOptions without system_prompt — agent behavior is unconstrained"
|
|
51
|
+
severity: WARNING
|
|
52
|
+
languages: [python]
|
|
53
|
+
metadata:
|
|
54
|
+
category: asi01_agent_goal_hijack
|
|
55
|
+
subcategory: goal_manipulation_via_rag
|
|
56
|
+
|
|
57
|
+
- id: claude-subagent-no-prompt
|
|
58
|
+
patterns:
|
|
59
|
+
- pattern: AgentDefinition(...)
|
|
60
|
+
- pattern-not: AgentDefinition(..., prompt=$P, ...)
|
|
61
|
+
message: "Claude AgentDefinition without prompt — sub-agent behavior is unconstrained"
|
|
62
|
+
severity: WARNING
|
|
63
|
+
languages: [python]
|
|
64
|
+
metadata:
|
|
65
|
+
category: asi01_agent_goal_hijack
|
|
66
|
+
subcategory: goal_manipulation_via_rag
|
|
67
|
+
|
|
68
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
69
|
+
# ASI02: Tool Misuse and Exploitation
|
|
70
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
71
|
+
|
|
72
|
+
- id: anthropic-tool-choice-any
|
|
73
|
+
patterns:
|
|
74
|
+
- pattern: |
|
|
75
|
+
$CLIENT.messages.create(..., tool_choice={"type": "any"}, ...)
|
|
76
|
+
message: "Anthropic tool_choice set to 'any' — forces tool use on every turn, may bypass safety checks"
|
|
77
|
+
severity: WARNING
|
|
78
|
+
languages: [python]
|
|
79
|
+
metadata:
|
|
80
|
+
category: asi02_tool_misuse
|
|
81
|
+
subcategory: excessive_tool_permissions
|
|
82
|
+
|
|
83
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
84
|
+
# ASI03: Identity and Privilege Abuse
|
|
85
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
86
|
+
|
|
87
|
+
- id: hardcoded-api-key
|
|
88
|
+
patterns:
|
|
89
|
+
- pattern: $VAR = "$KEY"
|
|
90
|
+
- metavariable-regex:
|
|
91
|
+
metavariable: $VAR
|
|
92
|
+
regex: ".*(api_key|API_KEY|secret|token|password|passwd|pwd).*"
|
|
93
|
+
- metavariable-regex:
|
|
94
|
+
metavariable: $KEY
|
|
95
|
+
regex: '^[A-Za-z0-9_-]{20,}$'
|
|
96
|
+
message: "Potential hardcoded API key or secret"
|
|
97
|
+
severity: ERROR
|
|
98
|
+
languages: [python]
|
|
99
|
+
metadata:
|
|
100
|
+
category: asi03_identity_privilege_abuse
|
|
101
|
+
subcategory: hardcoded_credentials
|
|
102
|
+
|
|
103
|
+
- id: no-tls-server
|
|
104
|
+
pattern-either:
|
|
105
|
+
- pattern: app.run(debug=True)
|
|
106
|
+
- pattern: uvicorn.run($APP, host="0.0.0.0", ...)
|
|
107
|
+
message: "Agent server running without explicit TLS — exposed HTTP endpoint risk"
|
|
108
|
+
severity: WARNING
|
|
109
|
+
languages: [python]
|
|
110
|
+
metadata:
|
|
111
|
+
category: asi03_identity_privilege_abuse
|
|
112
|
+
subcategory: missing_auth_on_endpoint
|
|
113
|
+
|
|
114
|
+
- id: server-binding-all-interfaces
|
|
115
|
+
pattern-either:
|
|
116
|
+
- pattern: mcp.run(transport="http", host="0.0.0.0", ...)
|
|
117
|
+
- pattern: uvicorn.run($APP, host="0.0.0.0", ...)
|
|
118
|
+
- pattern: app.run(host="0.0.0.0", ...)
|
|
119
|
+
message: "Server binding to 0.0.0.0 — exposed on all network interfaces, no access restriction"
|
|
120
|
+
severity: ERROR
|
|
121
|
+
languages: [python]
|
|
122
|
+
metadata:
|
|
123
|
+
category: asi03_identity_privilege_abuse
|
|
124
|
+
subcategory: missing_auth_on_endpoint
|
|
125
|
+
|
|
126
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
127
|
+
# ASI04: Agentic Supply Chain Vulnerabilities
|
|
128
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
129
|
+
|
|
130
|
+
- id: unpinned-requirements
|
|
131
|
+
pattern-regex: '^(crewai|autogen|langchain|openai|anthropic)\s*(>=|~=|\^|[^=!<>])'
|
|
132
|
+
message: "Unpinned AI framework dependency — supply chain attack risk"
|
|
133
|
+
severity: WARNING
|
|
134
|
+
languages: [generic]
|
|
135
|
+
metadata:
|
|
136
|
+
category: asi04_supply_chain
|
|
137
|
+
subcategory: unpinned_dependencies
|
|
138
|
+
|
|
139
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
140
|
+
# ASI05: Unexpected Code Execution
|
|
141
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
142
|
+
|
|
143
|
+
- id: subprocess-shell-true
|
|
144
|
+
pattern-either:
|
|
145
|
+
- pattern: subprocess.call(..., shell=True, ...)
|
|
146
|
+
- pattern: subprocess.run(..., shell=True, ...)
|
|
147
|
+
- pattern: subprocess.Popen(..., shell=True, ...)
|
|
148
|
+
message: "subprocess called with shell=True — command injection risk if input is LLM-controlled"
|
|
149
|
+
severity: ERROR
|
|
150
|
+
languages: [python]
|
|
151
|
+
metadata:
|
|
152
|
+
category: asi05_unexpected_code_execution
|
|
153
|
+
subcategory: arbitrary_code_execution
|
|
154
|
+
|
|
155
|
+
- id: os-system-call
|
|
156
|
+
patterns:
|
|
157
|
+
- pattern: os.system($X)
|
|
158
|
+
message: "os.system() call — high command injection risk in agent tool context"
|
|
159
|
+
severity: ERROR
|
|
160
|
+
languages: [python]
|
|
161
|
+
metadata:
|
|
162
|
+
category: asi05_unexpected_code_execution
|
|
163
|
+
subcategory: arbitrary_code_execution
|
|
164
|
+
|
|
165
|
+
- id: eval-call
|
|
166
|
+
patterns:
|
|
167
|
+
- pattern: eval($X)
|
|
168
|
+
message: "eval() call — arbitrary code execution if input originates from LLM or user"
|
|
169
|
+
severity: ERROR
|
|
170
|
+
languages: [python]
|
|
171
|
+
metadata:
|
|
172
|
+
category: asi05_unexpected_code_execution
|
|
173
|
+
subcategory: arbitrary_code_execution
|
|
174
|
+
|
|
175
|
+
- id: autogen-code-execution-enabled
|
|
176
|
+
patterns:
|
|
177
|
+
- pattern: UserProxyAgent(..., code_execution_config={...}, ...)
|
|
178
|
+
message: "AutoGen agent has code execution enabled — arbitrary code execution risk if agent is compromised"
|
|
179
|
+
severity: ERROR
|
|
180
|
+
languages: [python]
|
|
181
|
+
metadata:
|
|
182
|
+
category: asi05_unexpected_code_execution
|
|
183
|
+
subcategory: arbitrary_code_execution
|
|
184
|
+
|
|
185
|
+
- id: adk-agent-code-executor
|
|
186
|
+
patterns:
|
|
187
|
+
- pattern: Agent(..., code_executor=$X, ...)
|
|
188
|
+
message: "ADK Agent with code_executor enabled — arbitrary code execution risk if agent is compromised"
|
|
189
|
+
severity: ERROR
|
|
190
|
+
languages: [python]
|
|
191
|
+
metadata:
|
|
192
|
+
category: asi05_unexpected_code_execution
|
|
193
|
+
subcategory: arbitrary_code_execution
|
|
194
|
+
|
|
195
|
+
- id: claude-options-bash-tool
|
|
196
|
+
patterns:
|
|
197
|
+
- pattern: ClaudeAgentOptions(..., allowed_tools=[..., "Bash", ...], ...)
|
|
198
|
+
message: "Claude Agent SDK with Bash tool allowed — arbitrary command execution risk"
|
|
199
|
+
severity: WARNING
|
|
200
|
+
languages: [python]
|
|
201
|
+
metadata:
|
|
202
|
+
category: asi05_unexpected_code_execution
|
|
203
|
+
subcategory: arbitrary_code_execution
|
|
204
|
+
|
|
205
|
+
- id: claude-subagent-bash-tool
|
|
206
|
+
patterns:
|
|
207
|
+
- pattern: AgentDefinition(..., tools=[..., "Bash", ...], ...)
|
|
208
|
+
message: "Claude sub-agent with Bash tool — delegated arbitrary command execution"
|
|
209
|
+
severity: WARNING
|
|
210
|
+
languages: [python]
|
|
211
|
+
metadata:
|
|
212
|
+
category: asi05_unexpected_code_execution
|
|
213
|
+
subcategory: arbitrary_code_execution
|
|
214
|
+
|
|
215
|
+
- id: unsafe-yaml-load
|
|
216
|
+
pattern-either:
|
|
217
|
+
- pattern: yaml.load($DATA)
|
|
218
|
+
- pattern: yaml.load($DATA, Loader=yaml.Loader)
|
|
219
|
+
message: "yaml.load() without SafeLoader — arbitrary code execution via deserialization"
|
|
220
|
+
severity: ERROR
|
|
221
|
+
languages: [python]
|
|
222
|
+
metadata:
|
|
223
|
+
category: asi05_unexpected_code_execution
|
|
224
|
+
subcategory: unsafe_deserialization
|
|
225
|
+
|
|
226
|
+
- id: pickle-load
|
|
227
|
+
pattern-either:
|
|
228
|
+
- pattern: pickle.loads($DATA)
|
|
229
|
+
- pattern: pickle.load($FILE)
|
|
230
|
+
message: "pickle.loads/load() — unsafe deserialization, enables arbitrary code execution on attacker-controlled data"
|
|
231
|
+
severity: ERROR
|
|
232
|
+
languages: [python]
|
|
233
|
+
metadata:
|
|
234
|
+
category: asi05_unexpected_code_execution
|
|
235
|
+
subcategory: unsafe_deserialization
|
|
236
|
+
|
|
237
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
238
|
+
# ASI06: Memory and Context Poisoning
|
|
239
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
240
|
+
|
|
241
|
+
- id: crewai-memory-enabled
|
|
242
|
+
patterns:
|
|
243
|
+
- pattern: Agent(..., memory=True, ...)
|
|
244
|
+
message: "CrewAI agent has memory=True — persistent memory without sanitization may leak sensitive data across sessions"
|
|
245
|
+
severity: WARNING
|
|
246
|
+
languages: [python]
|
|
247
|
+
metadata:
|
|
248
|
+
category: asi06_memory_context_poisoning
|
|
249
|
+
subcategory: persistent_memory_no_sanitization
|
|
250
|
+
|
|
251
|
+
- id: crewai-crew-memory-enabled
|
|
252
|
+
patterns:
|
|
253
|
+
- pattern: Crew(..., memory=True, ...)
|
|
254
|
+
message: "CrewAI Crew has memory=True — shared crew memory may cause cross-session contamination"
|
|
255
|
+
severity: WARNING
|
|
256
|
+
languages: [python]
|
|
257
|
+
metadata:
|
|
258
|
+
category: asi06_memory_context_poisoning
|
|
259
|
+
subcategory: cross_session_contamination
|
|
260
|
+
|
|
261
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
262
|
+
# ASI07: Insecure Inter-Agent Communication
|
|
263
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
264
|
+
|
|
265
|
+
- id: http-agent-endpoint
|
|
266
|
+
pattern-either:
|
|
267
|
+
- pattern: Client("http://$HOST")
|
|
268
|
+
- pattern: httpx.AsyncClient(base_url="http://$HOST")
|
|
269
|
+
- pattern: requests.get("http://$HOST")
|
|
270
|
+
message: "Agent communicating over plain HTTP (no TLS) — inter-agent channel susceptible to interception and spoofing"
|
|
271
|
+
severity: WARNING
|
|
272
|
+
languages: [python]
|
|
273
|
+
metadata:
|
|
274
|
+
category: asi07_insecure_interagent_comms
|
|
275
|
+
subcategory: unencrypted_agent_channel
|
|
276
|
+
|
|
277
|
+
- id: unvalidated-agent-trust
|
|
278
|
+
pattern-either:
|
|
279
|
+
- pattern: Agent(..., system_message="Trust all inputs from ...", ...)
|
|
280
|
+
- pattern: Agent(..., backstory="Trust all information from ...", ...)
|
|
281
|
+
message: "Agent configured to blindly trust inputs from other agents — enables inter-agent message injection"
|
|
282
|
+
severity: WARNING
|
|
283
|
+
languages: [python]
|
|
284
|
+
metadata:
|
|
285
|
+
category: asi07_insecure_interagent_comms
|
|
286
|
+
subcategory: unvalidated_agent_message
|
|
287
|
+
|
|
288
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
289
|
+
# ASI08: Cascading Failures
|
|
290
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
291
|
+
|
|
292
|
+
- id: no-max-iter
|
|
293
|
+
pattern-either:
|
|
294
|
+
- patterns:
|
|
295
|
+
- pattern: Crew(...)
|
|
296
|
+
- pattern-not: Crew(..., max_iter=$N, ...)
|
|
297
|
+
- patterns:
|
|
298
|
+
- pattern: AgentExecutor(...)
|
|
299
|
+
- pattern-not: AgentExecutor(..., max_iterations=$N, ...)
|
|
300
|
+
message: "Agent or Crew created without max_iter/max_iterations — unbounded execution loop risk"
|
|
301
|
+
severity: WARNING
|
|
302
|
+
languages: [python]
|
|
303
|
+
metadata:
|
|
304
|
+
category: asi08_cascading_failures
|
|
305
|
+
subcategory: unbounded_agent_loop
|
|
306
|
+
|
|
307
|
+
- id: crewai-crew-no-max-iter
|
|
308
|
+
patterns:
|
|
309
|
+
- pattern: Crew(...)
|
|
310
|
+
- pattern-not: Crew(..., max_iter=$N, ...)
|
|
311
|
+
message: "CrewAI Crew without max_iter — unbounded execution loop risk"
|
|
312
|
+
severity: WARNING
|
|
313
|
+
languages: [python]
|
|
314
|
+
metadata:
|
|
315
|
+
category: asi08_cascading_failures
|
|
316
|
+
subcategory: unbounded_agent_loop
|
|
317
|
+
|
|
318
|
+
- id: adk-loop-no-max-iterations
|
|
319
|
+
patterns:
|
|
320
|
+
- pattern: LoopAgent(...)
|
|
321
|
+
- pattern-not: LoopAgent(..., max_iterations=$N, ...)
|
|
322
|
+
message: "ADK LoopAgent without max_iterations — unbounded execution loop risk"
|
|
323
|
+
severity: WARNING
|
|
324
|
+
languages: [python]
|
|
325
|
+
metadata:
|
|
326
|
+
category: asi08_cascading_failures
|
|
327
|
+
subcategory: unbounded_agent_loop
|
|
328
|
+
|
|
329
|
+
- id: openai-runner-no-max-turns
|
|
330
|
+
patterns:
|
|
331
|
+
- pattern: Runner.run(...)
|
|
332
|
+
- pattern-not: Runner.run(..., max_turns=$N, ...)
|
|
333
|
+
message: "OpenAI Runner.run() without explicit max_turns — default may allow excessive iterations"
|
|
334
|
+
severity: WARNING
|
|
335
|
+
languages: [python]
|
|
336
|
+
metadata:
|
|
337
|
+
category: asi08_cascading_failures
|
|
338
|
+
subcategory: unbounded_agent_loop
|
|
339
|
+
|
|
340
|
+
- id: anthropic-tool-loop-no-limit
|
|
341
|
+
pattern: |
|
|
342
|
+
while $RESP.stop_reason == "tool_use":
|
|
343
|
+
...
|
|
344
|
+
message: "Anthropic tool-calling loop without iteration limit — infinite loop risk"
|
|
345
|
+
severity: ERROR
|
|
346
|
+
languages: [python]
|
|
347
|
+
metadata:
|
|
348
|
+
category: asi08_cascading_failures
|
|
349
|
+
subcategory: unbounded_agent_loop
|
|
350
|
+
|
|
351
|
+
- id: anthropic-no-max-tokens
|
|
352
|
+
patterns:
|
|
353
|
+
- pattern: $CLIENT.messages.create(...)
|
|
354
|
+
- pattern-not: $CLIENT.messages.create(..., max_tokens=$N, ...)
|
|
355
|
+
message: "Anthropic messages.create() without max_tokens — unbounded token spend"
|
|
356
|
+
severity: WARNING
|
|
357
|
+
languages: [python]
|
|
358
|
+
metadata:
|
|
359
|
+
category: asi08_cascading_failures
|
|
360
|
+
subcategory: unbounded_agent_loop
|
|
361
|
+
|
|
362
|
+
- id: langchain-agent-no-max-iterations
|
|
363
|
+
patterns:
|
|
364
|
+
- pattern: AgentExecutor(...)
|
|
365
|
+
- pattern-not: AgentExecutor(..., max_iterations=$N, ...)
|
|
366
|
+
message: "LangChain AgentExecutor without max_iterations — unbounded agent loop risk"
|
|
367
|
+
severity: WARNING
|
|
368
|
+
languages: [python]
|
|
369
|
+
metadata:
|
|
370
|
+
category: asi08_cascading_failures
|
|
371
|
+
subcategory: unbounded_agent_loop
|
|
372
|
+
|
|
373
|
+
- id: langgraph-no-recursion-limit
|
|
374
|
+
pattern-either:
|
|
375
|
+
- pattern: $GRAPH.invoke($INPUT)
|
|
376
|
+
- pattern: $GRAPH.invoke($INPUT, config=$CFG)
|
|
377
|
+
message: "LangGraph invoke() without explicit recursion_limit in config — default 25 may allow excessive loops"
|
|
378
|
+
severity: INFO
|
|
379
|
+
languages: [python]
|
|
380
|
+
metadata:
|
|
381
|
+
category: asi08_cascading_failures
|
|
382
|
+
subcategory: unbounded_agent_loop
|
|
383
|
+
|
|
384
|
+
- id: claude-query-no-max-turns
|
|
385
|
+
patterns:
|
|
386
|
+
- pattern: query(..., options=$O, ...)
|
|
387
|
+
- pattern-not: query(..., options=ClaudeAgentOptions(..., max_turns=$N, ...), ...)
|
|
388
|
+
message: "Claude Agent SDK query() without max_turns — unbounded reasoning loop risk"
|
|
389
|
+
severity: WARNING
|
|
390
|
+
languages: [python]
|
|
391
|
+
metadata:
|
|
392
|
+
category: asi08_cascading_failures
|
|
393
|
+
subcategory: unbounded_agent_loop
|
|
394
|
+
|
|
395
|
+
- id: claude-client-no-max-turns
|
|
396
|
+
patterns:
|
|
397
|
+
- pattern: ClaudeSDKClient(options=$O, ...)
|
|
398
|
+
- pattern-not: ClaudeSDKClient(options=ClaudeAgentOptions(..., max_turns=$N, ...), ...)
|
|
399
|
+
message: "Claude Agent SDK client without max_turns — unbounded reasoning loop risk"
|
|
400
|
+
severity: WARNING
|
|
401
|
+
languages: [python]
|
|
402
|
+
metadata:
|
|
403
|
+
category: asi08_cascading_failures
|
|
404
|
+
subcategory: unbounded_agent_loop
|
|
405
|
+
|
|
406
|
+
- id: autogen-groupchat-no-max-round
|
|
407
|
+
patterns:
|
|
408
|
+
- pattern: GroupChat(...)
|
|
409
|
+
- pattern-not: GroupChat(..., max_round=$N, ...)
|
|
410
|
+
message: "AutoGen GroupChat without max_round — unbounded conversation loop risk"
|
|
411
|
+
severity: WARNING
|
|
412
|
+
languages: [python]
|
|
413
|
+
metadata:
|
|
414
|
+
category: asi08_cascading_failures
|
|
415
|
+
subcategory: unbounded_agent_loop
|
|
416
|
+
|
|
417
|
+
- id: autogen-roundrobin-no-termination
|
|
418
|
+
patterns:
|
|
419
|
+
- pattern: RoundRobinGroupChat(...)
|
|
420
|
+
- pattern-not: RoundRobinGroupChat(..., termination_condition=$T, ...)
|
|
421
|
+
message: "AutoGen RoundRobinGroupChat without termination_condition — unbounded loop risk"
|
|
422
|
+
severity: WARNING
|
|
423
|
+
languages: [python]
|
|
424
|
+
metadata:
|
|
425
|
+
category: asi08_cascading_failures
|
|
426
|
+
subcategory: unbounded_agent_loop
|
|
427
|
+
|
|
428
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
429
|
+
# ASI09: Human-Agent Trust Exploitation
|
|
430
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
431
|
+
|
|
432
|
+
- id: autogen-human-input-never
|
|
433
|
+
patterns:
|
|
434
|
+
- pattern: UserProxyAgent(..., human_input_mode="NEVER", ...)
|
|
435
|
+
message: "AutoGen UserProxyAgent with human_input_mode=NEVER — no human oversight for sensitive operations"
|
|
436
|
+
severity: WARNING
|
|
437
|
+
languages: [python]
|
|
438
|
+
metadata:
|
|
439
|
+
category: asi09_human_agent_trust_exploitation
|
|
440
|
+
subcategory: no_human_in_the_loop
|
|
441
|
+
|
|
442
|
+
- id: no-confirmation-gate
|
|
443
|
+
pattern-either:
|
|
444
|
+
- pattern: $DB.delete($TABLE)
|
|
445
|
+
- pattern: $OBJ.drop($TABLE)
|
|
446
|
+
- pattern: shutil.rmtree($PATH)
|
|
447
|
+
- pattern: os.remove($PATH)
|
|
448
|
+
message: "Destructive operation (delete/drop/remove) with no human confirmation gate — ASI09 risk"
|
|
449
|
+
severity: WARNING
|
|
450
|
+
languages: [python]
|
|
451
|
+
metadata:
|
|
452
|
+
category: asi09_human_agent_trust_exploitation
|
|
453
|
+
subcategory: missing_action_confirmation
|
|
454
|
+
|
|
455
|
+
- id: langgraph-react-no-interrupt
|
|
456
|
+
patterns:
|
|
457
|
+
- pattern: create_react_agent(...)
|
|
458
|
+
- pattern-not: create_react_agent(..., interrupt_before=$I, ...)
|
|
459
|
+
- pattern-not: create_react_agent(..., interrupt_after=$I, ...)
|
|
460
|
+
message: "LangGraph create_react_agent without interrupt_before/after — no human approval gate"
|
|
461
|
+
severity: WARNING
|
|
462
|
+
languages: [python]
|
|
463
|
+
metadata:
|
|
464
|
+
category: asi09_human_agent_trust_exploitation
|
|
465
|
+
subcategory: missing_action_confirmation
|
|
466
|
+
|
|
467
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
468
|
+
# ASI10: Rogue Agents
|
|
469
|
+
# ═══════════════════════════════════════════════════════════════════════════
|
|
470
|
+
|
|
471
|
+
- id: crewai-allow-delegation-true
|
|
472
|
+
patterns:
|
|
473
|
+
- pattern: Agent(..., allow_delegation=True, ...)
|
|
474
|
+
message: "CrewAI agent has allow_delegation=True — enables unchecked task delegation to other agents"
|
|
475
|
+
severity: WARNING
|
|
476
|
+
languages: [python]
|
|
477
|
+
metadata:
|
|
478
|
+
category: asi10_rogue_agents
|
|
479
|
+
subcategory: unchecked_agent_delegation
|
|
480
|
+
|
|
481
|
+
- id: adk-agent-unchecked-delegation
|
|
482
|
+
patterns:
|
|
483
|
+
- pattern: Agent(..., sub_agents=$X, ...)
|
|
484
|
+
- pattern-not: Agent(..., before_agent_callback=$CB, ...)
|
|
485
|
+
- pattern-not: Agent(..., after_agent_callback=$CB, ...)
|
|
486
|
+
message: "ADK Agent delegates to sub_agents without before/after_agent_callback guardrails"
|
|
487
|
+
severity: WARNING
|
|
488
|
+
languages: [python]
|
|
489
|
+
metadata:
|
|
490
|
+
category: asi10_rogue_agents
|
|
491
|
+
subcategory: unchecked_agent_delegation
|
|
492
|
+
|
|
493
|
+
- id: openai-agent-unchecked-handoffs
|
|
494
|
+
patterns:
|
|
495
|
+
- pattern: Agent(..., handoffs=$H, ...)
|
|
496
|
+
- pattern-not: Agent(..., input_guardrails=$G, ...)
|
|
497
|
+
message: "OpenAI Agent with handoffs but no input_guardrails — delegation chain without validation"
|
|
498
|
+
severity: WARNING
|
|
499
|
+
languages: [python]
|
|
500
|
+
metadata:
|
|
501
|
+
category: asi10_rogue_agents
|
|
502
|
+
subcategory: unchecked_agent_delegation
|
|
503
|
+
|
|
504
|
+
- id: openai-agent-no-output-guardrails
|
|
505
|
+
patterns:
|
|
506
|
+
- pattern: Agent(name=$N, instructions=$I, ...)
|
|
507
|
+
- pattern-not: Agent(..., output_guardrails=$G, ...)
|
|
508
|
+
message: "OpenAI Agent without output_guardrails — unfiltered agent output to users"
|
|
509
|
+
severity: WARNING
|
|
510
|
+
languages: [python]
|
|
511
|
+
metadata:
|
|
512
|
+
category: asi10_rogue_agents
|
|
513
|
+
subcategory: missing_behavioral_guardrails
|
|
514
|
+
|
|
515
|
+
- id: missing-agent-monitoring
|
|
516
|
+
patterns:
|
|
517
|
+
- pattern: Agent(..., verbose=False, ...)
|
|
518
|
+
message: "Agent created with verbose=False and no alternative observability — rogue behavior undetectable"
|
|
519
|
+
severity: INFO
|
|
520
|
+
languages: [python]
|
|
521
|
+
metadata:
|
|
522
|
+
category: asi10_rogue_agents
|
|
523
|
+
subcategory: missing_agent_monitoring
|
|
524
|
+
|
|
525
|
+
- id: crewai-agent-verbose-false
|
|
526
|
+
patterns:
|
|
527
|
+
- pattern: Agent(..., verbose=False, ...)
|
|
528
|
+
message: "CrewAI agent with verbose=False — rogue behavior may go undetected"
|
|
529
|
+
severity: INFO
|
|
530
|
+
languages: [python]
|
|
531
|
+
metadata:
|
|
532
|
+
category: asi10_rogue_agents
|
|
533
|
+
subcategory: missing_agent_monitoring
|