Guides

Securing CrewAI Agents

Scan your CrewAI crews for security issues and add execution controls to multi-agent workflows.

CrewAI-specific risks

CrewAI's multi-agent model introduces attack surfaces that don't exist in single-agent systems. The trust boundary between agents is easy to miss.

  • Crew-to-crew communication — one compromised agent can inject malicious instructions to others. If agent A processes untrusted input and its output feeds agent B, A becomes an injection relay.
  • Tool delegation — agents can grant each other tool access at runtime. This is a privilege escalation vector: a restricted agent can obtain capabilities it was never supposed to have by routing through a more-privileged agent.
  • Memory persistence — unvalidated writes to shared crew memory allow injected content to persist and influence future agent runs, even after the original attacker input is gone.

Scanning a CrewAI crew

The scanner inspects your crew definition for tool exposure, delegation settings, and injection patterns across all agent definitions in the file.

python
import httpx

with open("my_crew.py") as f:
    code = f.read()

result = httpx.post("https://api.agentcop.live/api/scan", json={
    "code": code,
    "description": "CrewAI research and writing crew with web search"
}).json()

print(f"Trust Score: {result['trust_score']}/100")
for issue in result["issues"]:
    print(f"  [{issue['severity']}] {issue['type']}: {issue['description']}")

AgentBob's CrewAI crew

AgentBob's crew has allow_delegation=True on both agents and exposes a code interpreter tool with no gate — a combination that enables privilege escalation and arbitrary code execution.

python
from crewai import Agent, Task, Crew
from crewai_tools import CodeInterpreterTool

# AgentBob creates a crew with no controls
researcher = Agent(
    role="Researcher",
    goal="Research anything the user asks",
    tools=[CodeInterpreterTool()],  # LLM08: code execution without gate
    allow_delegation=True,  # Allows privilege escalation between agents
)

writer = Agent(
    role="Writer",
    goal="Write based on research",
    allow_delegation=True,
)

# No execution controls, no memory validation
crew = Crew(agents=[researcher, writer], tasks=[...])

Safe CrewAI pattern

Apply the principle of least privilege per agent. Researchers get search tools. Writers get no tools. Neither agent can delegate to the other.

python
from crewai import Agent, Task, Crew
from crewai_tools import SerperDevTool
# from agentcop import ExecutionGate, GatePolicy

# Principle of least privilege per agent
researcher = Agent(
    role="Research Specialist",
    goal="Research using only approved search tools",
    tools=[SerperDevTool()],       # Only search — no code execution
    allow_delegation=False,         # No delegation — prevents privilege escalation
    max_iter=5,                     # Bounded iteration prevents DoS
    verbose=True,
)

writer = Agent(
    role="Content Writer",
    goal="Write clear summaries",
    tools=[],                       # No external tools — writer only processes text
    allow_delegation=False,
)

# Scoped tasks with explicit expected output
research_task = Task(
    description="Research {topic} using web search only",
    expected_output="A factual summary with sources",
    agent=researcher,
)

Memory security

CrewAI's persistent memory is powerful but introduces a long-lived injection surface. Content written to memory in one session can influence agent behavior in future sessions.

  • Use crew.memory=True only with validated inputs — treat memory writes like database writes
  • Monitor what goes into persistent memory; log all write operations
  • Never allow user-controlled strings to be stored as "facts" — an attacker who poisons crew memory can influence every future run

Checklist

  • allow_delegation=False unless explicitly required
  • max_iter set on all agents
  • Tools scoped per agent (researcher ≠ writer)
  • No CodeInterpreterTool without gate
  • Memory writes validated