Awesome-omni-skill secure-agent
Locks down an AI agent by configuring platform-level tool restrictions (deniedTools) and Earl network egress rules. Use after Earl is working and templates are created, to make Earl's security guarantee enforceable rather than advisory.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/ai-agents/secure-agent" ~/.claude/skills/diegosouzapw-awesome-omni-skill-secure-agent && rm -rf "$T"
skills/ai-agents/secure-agent/SKILL.md- makes HTTP requests (curl)
- downloads files (wget)
Secure Agent
After Earl is set up and working, this skill restricts the agent's ability to bypass Earl and make raw API/CLI calls directly. Without this step, CLAUDE.md is just a suggestion.
What This Does
: Blocks specific bash commands (curl, gh, stripe-cli, etc.) at the platform level for Claude Code. Agents cannot run these commands at all.deniedTools- Egress rules: Restricts which URLs Earl templates can contact, preventing Earl itself from being used as an open proxy.
Important Limitation
deniedTools pattern matching can be bypassed via alternative tools (python3 -c "import urllib...", node -e "fetch(...)", etc.). This blocks accidental or habitual CLI use — the
common case. For stronger containment, pair with OS-level firewall rules or a network proxy.
Platform Support
| Platform | Mechanism | Hard restriction? |
|---|---|---|
| Claude Code | in | Yes — platform enforced |
| Cursor | or Cursor settings UI | Partial — check Cursor docs for per-tool restrictions |
| Windsurf | or Windsurf settings UI | Partial — check Windsurf docs for per-tool restrictions |
| Claude Desktop | No bash access | N/A |
| Non-MCP CLI agents | CLAUDE.md instructions only | No — advisory only |
This skill primarily targets Claude Code. Instructions for other platforms are best-effort.
Step 1: Check Coverage
Only deny tools for services that have Earl templates. Denying a tool for a service with no Earl template would leave the agent unable to interact with that service at all.
earl templates list --json
Note which providers are covered. Map each to the CLI tools to deny:
| Earl template covers | Deny these tools |
|---|---|
| , |
| |
| |
| |
| |
| Any HTTP API template | , , , |
| Any SQL template | , , |
| Any gRPC template | |
Do NOT deny
entirely. Earl's bash protocol and legitimate shell operations still
need it.Bash
Note on
and Bash(curl *)
: Denying these also blocks all non-API curl
uses — downloading binaries, health probes (Bash(wget *)
curl http://localhost:8080/health), fetching
install scripts, etc. If the agent legitimately needs curl for non-API tasks, add a narrow
allowedTools override for those specific patterns, or use earl call instead for all
HTTP operations.
Note on
: Denying Bash(gh *)
gh also blocks all gh CLI uses that are not API calls:
gh pr create, gh release upload, gh repo clone, branch management, etc. If the agent
needs gh for repository operations that don't have Earl templates, add narrow exceptions or
create templates for those commands before denying Bash(gh *).
Step 2: Generate and Present Denylist
Based on the covered providers, generate the
deniedTools array. Show it to the user before
applying anything:
"Based on your Earl templates, I'd add these restrictions to
:.claude/settings.json{ "deniedTools": [ "Bash(curl *)", "Bash(wget *)", "Bash(gh *)", "Bash(stripe *)" ] }This blocks the listed tools for this agent in this project. Other projects are unaffected. Shall I apply this?"
Do not apply until the user explicitly approves.
Step 3: Apply Denylist
For Claude Code: read
.claude/settings.json, merge the deniedTools array (do not overwrite
other keys), write it back.
If
deniedTools already exists, merge arrays — do not duplicate entries.
Step 4: Verify
For Claude Code: Attempt to run a denied command:
curl https://example.com
Claude Code will refuse to run this command. The "tool denied" or "not allowed" error message from Claude Code is the success signal — it means the denylist is active. You cannot distinguish success from failure by looking at the exit code; look at whether Claude Code blocked it before the shell ran it.
If Claude Code runs
curl without blocking it, the deniedTools pattern syntax is wrong.
Check the format against current Claude Code documentation (search "deniedTools settings" in
the Claude Code docs or at https://docs.anthropic.com/en/docs/claude-code) — the exact pattern
syntax may vary by version. Then re-apply with the corrected format.
For other platforms: Ask the user to attempt a denied command manually in their agent session and confirm it is blocked.
Test that Earl still works:
earl templates list
Expected: succeeds and lists available templates (Earl is not in the denylist).
Step 5: Configure Egress Rules (Strongly Recommended)
Without egress rules, Earl is an open proxy — any HTTP template with a parameterized URL can reach any public endpoint. Add
[[network.allow]] rules to
~/.config/earl/config.toml (macOS/Linux) or %APPDATA%\earl\config.toml (Windows)
to restrict which hosts Earl templates can contact.
Note: Egress rules are global — they apply to all projects using this Earl install. Earl does not currently support per-project config files.
For each provider template, add a rule:
[[network.allow]] hosts = ["api.github.com"] [[network.allow]] hosts = ["api.stripe.com"] [[network.allow]] hosts = ["api.slack.com", "slack.com"]
Security note on environments: If any template uses
allow_environment_protocol_switching = true in its annotations, an environment override can silently switch protocols (e.g. from
HTTP to bash). Review templates with this annotation carefully — a staging environment that
switches to bash bypasses the HTTP egress rules above. Prefer vars.* for environment
differences (e.g. different base URLs) over full protocol switching where possible.
After editing, verify:
earl doctor
Earl doctor checks that the config is valid. Any
[[network.allow]] parse errors will be
reported.
What This Does Not Cover
- Bash templates: The
protocol runs user-defined scripts in Earl's sandbox. The denylist does not restrict what Earl's own bash protocol can do. Ensure bash templates explicitly setbash
unless network access is required.sandbox.network = false - Agents without per-tool restriction: For non-Claude-Code agents, the CLAUDE.md instruction is the only constraint. This is advisory, not enforced.
- Alternative interpreters: Python, Node, Ruby, and other interpreters are not blocked by a curl-specific denylist. Pair with OS-level firewall rules for stronger containment.
Next Steps
- Earl is now the enforced channel for all covered API calls
- To add egress rules for a new provider: add
blocks to[[network.allow]]~/.config/earl/config.toml - If the agent is blocked from a call it needs: add an Earl template for that service, or remove the specific deny rule for that tool
- If something breaks: invoke
troubleshoot-earl