| name | description | allowed-tools | user-invocable |
|---|---|---|---|
awf-skill |
Use the AWF (Agentic Workflow Firewall) to run commands with network isolation and domain whitelisting. Provides L7 HTTP/HTTPS egress control for AI agents. |
Bash(sudo:*), Bash(awf:*), Bash(docker:*), Read |
false |
Use this skill when you need to run commands with network isolation, restrict network access to approved domains, or execute AI agents in a sandboxed environment with controlled network access.
AWF is a network firewall for agentic workflows that provides:
- L7 Domain Whitelisting: Control HTTP/HTTPS traffic at the application layer
- Host-Level Enforcement: Uses iptables DOCKER-USER chain to enforce firewall on ALL containers
- Chroot Mode: Optional transparent access to host binaries (Python, Node.js, Go) while maintaining network isolation
Use AWF when:
- Running AI agents (Copilot CLI, Claude, etc.) that need network access but should be restricted
- Testing code that makes network requests in a controlled environment
- Enforcing network security policies for automated workflows
- Running untrusted commands with limited network access
- Testing Playwright or other tools against localhost services
# Run a command with only github.com allowed
sudo awf --allow-domains github.com -- curl https://api.github.comThe -- separator divides firewall options from the command to run.
# This should FAIL (example.com not allowed)
sudo awf --allow-domains github.com -- curl -f --max-time 10 https://example.comsudo awf --allow-domains github.com --log-level debug -- curl https://api.github.comcurl -sSL https://raw.githubusercontent.com/github/gh-aw-firewall/main/install.sh | sudo bash
sudo awf --versiongit clone https://github.com/github/gh-aw-firewall.git awf
cd awf
npm install
npm run build
npm linksudo awf [options] -- <command>
Domain Options:
--allow-domains <domains> Comma-separated allowed domains
--allow-domains-file <path> File with allowed domains (one per line)
--block-domains <domains> Comma-separated blocked domains (takes precedence)
--block-domains-file <path> File with blocked domains
Network Options:
--dns-servers <servers> DNS servers (default: 8.8.8.8,8.8.4.4)
--enable-host-access Enable access to host via host.docker.internal
--allow-host-ports <ports> Ports to allow with host access (e.g., 3000,8080)
Container Options:
--tty Allocate TTY for interactive tools
--env KEY=VALUE Pass environment variable (repeatable)
--env-all Pass all host environment variables
--mount <host:container[:mode]> Volume mount (repeatable)
--container-workdir <dir> Working directory inside container
--agent-image <value> Agent image preset (default, act) or custom
Advanced Options:
--ssl-bump Enable HTTPS content inspection
--allow-urls <urls> URL patterns for SSL Bump (requires --ssl-bump)
Debugging Options:
--log-level <level> Log level: debug, info, warn, error
--keep-containers Keep containers after command exits
--proxy-logs-dir <path> Directory to save Squid logs to
# github.com also allows api.github.com, raw.github.com, etc.
sudo awf --allow-domains github.com -- curl https://api.github.com# Match any subdomain
--allow-domains '*.github.com'
# Match prefix patterns
--allow-domains 'api-*.example.com'
# Combine multiple patterns
--allow-domains 'github.com,*.googleapis.com,api-*.example.com'# HTTPS only
--allow-domains 'https://secure.example.com'
# HTTP only
--allow-domains 'http://legacy.example.com'# Allow domain but block specific subdomain
sudo awf \
--allow-domains example.com \
--block-domains internal.example.com \
-- curl https://api.example.com # Workssudo awf \
--allow-domains github.com,api.github.com,githubusercontent.com,anthropic.com \
-- copilot --prompt "List my repositories"sudo awf \
--allow-domains github.com,arxiv.org,mcp.tavily.com \
--log-level debug \
-- copilot --mcp arxiv,tavily --prompt "Search arxiv for recent AI papers"# The localhost keyword auto-configures host access and dev ports
sudo awf \
--allow-domains localhost,playwright.dev \
-- npx playwright test# Pass specific variables
sudo awf --allow-domains github.com \
-e GITHUB_TOKEN="$GITHUB_TOKEN" \
-e NODE_ENV=production \
-- npm test
# Pass all host environment variables
sudo awf --allow-domains github.com --env-all -- npm testsudo awf --allow-domains github.com \
-v /path/to/data:/data:ro \
-- cat /data/config.json# Access host Python, Node, Go, etc. (chroot mode is the default)
sudo awf --allow-domains api.github.com \
-- python3 -c "import requests; print(requests.get('https://api.github.com').status_code)"sudo awf \
--allow-domains github.com \
--ssl-bump \
--allow-urls "https://github.com/myorg/*" \
-- curl https://github.com/myorg/some-repo- name: Setup awf
uses: github/gh-aw-firewall@main
- name: Run with firewall
run: |
sudo -E awf --allow-domains github.com -- 'cd $GITHUB_WORKSPACE && npm test'# Pretty format (default)
awf logs
# Follow in real-time
awf logs -f
# JSON format for scripting
awf logs --format json
# List available log sources
awf logs --list# Terminal output
awf logs stats
# JSON for scripting
awf logs stats --format json
# Markdown for GitHub Actions
awf logs summary >> $GITHUB_STEP_SUMMARY# Using awf logs
awf logs --format json | jq 'select(.isAllowed == false)'
# Direct Squid log query
sudo grep "TCP_DENIED" /tmp/squid-logs-*/access.logsudo awf --allow-domains github.com --keep-containers -- failing-command
# Inspect containers
docker logs awf-squid
docker logs awf-agent
# View Squid config
docker exec awf-squid cat /etc/squid/squid.conf
# Manual cleanup when done
docker rm -f awf-squid awf-agent# After command completes
sudo cat /tmp/squid-logs-*/access.log | grep TCP_DENIED
# Or use the logs command
awf logs --format json | jq 'select(.isAllowed == false) | .domain'# Check iptables rules
docker exec awf-agent iptables -t nat -L OUTPUT -n -v
# Check DNS
docker exec awf-agent cat /etc/resolv.conf
# Test connectivity to Squid
docker exec awf-agent nc -zv 172.30.0.10 3128When analyzing logs, these codes indicate the traffic decision:
| Code | Meaning |
|---|---|
TCP_TUNNEL:HIER_DIRECT |
ALLOWED (HTTPS tunnel) |
TCP_MISS:HIER_DIRECT |
ALLOWED (HTTP request) |
TCP_DENIED:HIER_NONE |
BLOCKED (domain not in allowlist) |
# Default - minimal ubuntu:22.04 (~200MB)
sudo awf --agent-image default --allow-domains github.com -- command
# Act - GitHub Actions parity (~2GB)
sudo awf --agent-image act --allow-domains github.com -- commandsudo awf \
--build-local \
--agent-image ghcr.io/catthehacker/ubuntu:runner-22.04 \
--allow-domains github.com \
-- commandsudo systemctl start dockerdocker stop $(docker ps -q --filter "expose=3128")- Check if subdomain is needed:
api.example.comvsexample.com - Enable debug logging:
--log-level debug - Check Squid logs:
awf logs --format json
The domain is being blocked. Check:
- Is domain in
--allow-domains? - Is subdomain required?
- View blocked domains:
awf logs --format json | jq 'select(.isAllowed == false)'
- No IPv6: Only IPv4 traffic is supported
- No HTTP/3: Container curl doesn't support HTTP/3
- No internationalized domains: Use punycode (e.g.,
xn--bcher-kva.ch) - HTTP to HTTPS redirects: May fail; use HTTPS directly
- IP-based access: Direct IP access is blocked (no domain)
- Start with minimal domains: Only add what's needed
- Use wildcards carefully:
*.example.comis safer than* - Enable debug logging: When troubleshooting add
--log-level debug - Review logs: Check what was blocked with
awf logs stats - Use blocklists: For fine-grained control when allowing broad domains
- Quote shell commands: Use
'command $VAR'to preserve container expansion
To install this skill for Claude Code agents in your project:
# Download the skill
mkdir -p .claude/skills/awf-skill
curl -sSL https://raw.githubusercontent.com/github/gh-aw-firewall/main/skill.md \
-o .claude/skills/awf-skill/SKILL.mddebug-firewall- Manual Docker debugging commands for AWFawf-debug-tools- Python scripts for log parsing and diagnostics