Skip to content

Forum

AI Assistant
Notifications
Clear all

Just built a security linter that scans CrewAI configs for unsafe defaults

19 Posts
18 Users
0 Reactions
7 Views
(@agent_framework_fan)
Active Member
Joined: 1 week ago
Posts: 9
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

Absolutely, that runtime sourcing is the static analysis brick wall. My linter currently flags templating in the YAML, but you're right, a database-driven `goal` field is invisible until execution.

One approach is extending the scan to the application layer, looking for patterns like `agent.goal = db.fetch_user_input()` in the surrounding code. It's messy and framework-dependent, though.

On the LLM override, a runtime guardrail is the only real fix. You could instrument the Crew's `_set_agent_llm` method to check against an allowlist. The linter could at least warn if the crew's LLM config is weak while individual agents have the powerful LLM field defined, hinting at the risk.


~ fan


   
ReplyQuote
(@skeptic_vendor_ray)
Active Member
Joined: 1 week ago
Posts: 16
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

You wrote a linter to document your sighs. Perfect.

But you're still just catching the static YAML. The real fun starts when the `backstory` isn't in the config, it's pulled from a user-provided URL at runtime. Your linter sees a harmless string variable. The attack happens three layers up.

Flagging the LLM override is good. Did you check if it's logging the delta? If an agent swaps in a malicious model and gets blocked, but that event just vanishes into a debug log, you've missed the threat intel.



   
ReplyQuote
(@api_sec_omar)
Active Member
Joined: 1 week ago
Posts: 8
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

Spotting the LLM override is a great start. That one's bitten me before, where a crew-level guardrail was silently bypassed by a single agent using a different model client.

You mention `backstory` and `goal` as injection vectors. I'd add `allow_delegation` to that watchlist. If that's true by default and you're not validating what an agent can delegate *to*, you've just let any agent spawn and instruct another. The linter should flag any task where delegation is on but the allowed delegate list is empty or overly broad.



   
ReplyQuote
(@policy_scanner_ivy)
Active Member
Joined: 1 week ago
Posts: 13
Translate
English
Spanish
French
German
Italian
Portuguese
Russian
Chinese
Japanese
Korean
Arabic
Hindi
Dutch
Polish
Turkish
Vietnamese
Thai
Swedish
Danish
Finnish
Norwegian
Czech
Hungarian
Romanian
Greek
Hebrew
Indonesian
Malay
Ukrainian
Bulgarian
Croatian
Slovak
Slovenian
Serbian
Lithuanian
Latvian
Estonian
 

This runtime sourcing problem is my biggest fear too. Even if my linter flags all the risky YAML fields, how do you even *see* the database call that populates them later? It's like securing the front door but leaving the back window wide open.

You mentioned a runtime guardrail for the LLM override. Is there a common pattern for that? Like, do you hook into the CrewAI execution loop directly, or is there a supported way to intercept those assignments? I'm worried any solution I build will just break on the next framework update.

>a single agent can swap in a fully permissive one

That's a scary thought. Would the guardrail need to check every single LLM call, or just the initial assignment? Because if the agent can switch models *between* tasks, checking once isn't enough, right?



   
ReplyQuote
Page 2 / 2