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.

install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
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"
manifest: skills/ai-agents/secure-agent/SKILL.md
safety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
  • makes HTTP requests (curl)
  • downloads files (wget)
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content

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

  1. deniedTools
    : Blocks specific bash commands (curl, gh, stripe-cli, etc.) at the platform level for Claude Code. Agents cannot run these commands at all.
  2. 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

PlatformMechanismHard restriction?
Claude Code
deniedTools
in
.claude/settings.json
Yes — platform enforced
Cursor
.cursor/mcp.json
or Cursor settings UI
Partial — check Cursor docs for per-tool restrictions
Windsurf
.windsurf/mcp.json
or Windsurf settings UI
Partial — check Windsurf docs for per-tool restrictions
Claude DesktopNo bash accessN/A
Non-MCP CLI agentsCLAUDE.md instructions onlyNo — 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 coversDeny these tools
github
Bash(gh *)
,
Bash(hub *)
stripe
Bash(stripe *)
slack
Bash(slack *)
openai
Bash(openai *)
vercel
Bash(vercel *)
Any HTTP API template
Bash(curl *)
,
Bash(wget *)
,
Bash(http *)
,
Bash(httpie *)
Any SQL template
Bash(psql *)
,
Bash(mysql *)
,
Bash(sqlite3 *)
Any gRPC template
Bash(grpcurl *)

Do NOT deny

Bash
entirely. Earl's bash protocol and legitimate shell operations still need it.

Note on

Bash(curl *)
and
Bash(wget *)
:
Denying these also blocks all non-API curl uses — downloading binaries, health probes (
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

Bash(gh *)
: Denying
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
    bash
    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 set
    sandbox.network = false
    unless network access is required.
  • 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
    [[network.allow]]
    blocks to
    ~/.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