Agent Zero is a powerful open-source AI agent framework. Out of the box it is built for developer convenience, but deploying it in a corporate environment exposes several attack surfaces. This is what I hardened and why each change matters.
1. RFC (Remote Function Call) Endpoint — Disabled in Production
Agent Zero includes an RFC mechanism that lets the container call arbitrary Python functions on the host. In Docker mode this endpoint serves no legitimate purpose, but it was left enabled — meaning anyone who could reach the API could invoke os, subprocess, or any other Python module.
What I did:
- Disabled the
/rfcAPI endpoint entirely when running in Docker/production mode - Added a strict module prefix allowlist (
python.helpers.*,python.api.*,python.tools.*) so even in development, only internal agent-zero modules can be called via RFC
2. Skill Approval Workflow — Human-in-the-Loop Before Execution
Agent Zero can import and execute "skills" — small Python/markdown programs. Previously, imported skills were immediately active with no review step. A malicious or compromised skill source could push code straight into execution.
What I did:
- Introduced a
pending/andactive/subdirectory structure for skills - All newly imported skills land in
pending/and cannot run until explicitly approved - Added
skills_clicommands —list-pendingandpromote— that show the full skill content for human review before moving it toactive/
3. Browser Agent Hardening
The browser agent was configured with disable_security=True and accept_downloads=True — essentially a fully permissive headless browser running inside your network.
What I did:
- Set
disable_security=Falseto restore normal browser security boundaries - Set
accept_downloads=Falseto prevent drive-by file downloads - Added support for a
BROWSER_PROXYenvironment variable so browser traffic can be routed through a corporate proxy for monitoring and filtering - Added a prompt injection defence section to the browser agent's system prompt, explicitly instructing it to treat all web page content as untrusted data and never execute instructions found on pages it visits
4. Docker Hardening
The default compose file bound the agent port to 0.0.0.0 (all interfaces), used a bind mount of the entire project directory, and used the standard public image.
What I did:
- Bound the port to
127.0.0.1only, so it is never exposed on the network interface - Replaced the full bind mount with a named Docker volume scoped to
usr/(user data only) - Switched to a locally-built hardened image tag