Network-isolated sandbox for AI agents in GitHub Actions. Inspired by GitHub Next Agentic Workflows (gh-aw) Agent Workflow Firewall.
Runs your AI agent inside a Docker container on an isolated network. All HTTP/HTTPS traffic is routed through a Squid proxy that enforces a configurable domain allowlist. The agent can only reach domains you explicitly permit.
GitHub Actions Runner
+-------------------------------------------+
| Docker network (--internal) |
| |
| +-----------+ +----------------+ |
| | Agent |------->| Squid proxy |--+--> allowed domains
| | container | | | |
| | | | evil.com X | |
| | Your AI | | pastebin X | |
| | agent | | * X | |
| +-----------+ +----------------+ |
+-------------------------------------------+
- Creates an
--internalDocker network (no direct internet) - Starts a Squid proxy on that network, connected to bridge for outbound
- Runs the agent container on the isolated network with
HTTP_PROXY/HTTPS_PROXYset - Agent can only reach domains in the allowlist
- Proxy access log provides a full audit trail
- uses: microsoftgbb/agent-sandbox-action@v1
with:
command: |
copilot -p "Analyze this repo" --agent my-agent
allowed-domains: |
api.githubcopilot.com
api.github.comjobs:
diagnose:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
# Agent runs in network-isolated sandbox
- uses: microsoftgbb/agent-sandbox-action@v1
with:
command: |
copilot -p "Diagnose the cluster..." --agent cluster-doctor
allowed-domains: |
api.githubcopilot.com
api.github.com
.azmk8s.io
login.microsoftonline.com
env-vars: |
GITHUB_TOKEN=${{ secrets.COPILOT_CLI_TOKEN }}
extra-mounts: |
${{ env.HOME }}/.kube/config:/home/agent/.kube/config:ro
- uses: actions/upload-artifact@v4
with:
name: agent-output
path: agent-output.json
scan:
needs: diagnose
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
name: agent-output
# Validate, sanitize, and apply through safe-outputs gate
- uses: microsoftgbb/safe-outputs-action@v1
with:
artifact-path: agent-output.json
title-prefix: '[bot] '
threat-detection: trueThe default image includes Copilot CLI, kubectl, kubelogin, Python, and jq. To use a custom image with additional tools:
- uses: microsoftgbb/agent-sandbox-action@v1
with:
image: ghcr.io/my-org/my-agent-image:latest
command: my-custom-agent --analyze
allowed-domains: |
api.openai.com| Input | Description | Required | Default |
|---|---|---|---|
command |
Command to run inside the sandbox | Yes | - |
allowed-domains |
Newline-separated domain allowlist | Yes | - |
output-path |
Path where agent writes output | No | agent-output.json |
workspace-mount |
Host path to mount as /workspace |
No | $GITHUB_WORKSPACE |
extra-mounts |
Additional -v mounts, one per line |
No | '' |
env-vars |
Env vars for the agent, one per line | No | '' |
image |
Docker image for the agent container | No | ghcr.io/microsoftgbb/agent-sandbox:latest |
| Output | Description |
|---|---|
output-path |
Path to the agent output file on the host |
proxy-log |
Path to the Squid proxy access log (audit trail) |
exit-code |
Exit code of the agent command |
Uses Squid dstdomain syntax:
| Pattern | Matches |
|---|---|
api.github.com |
Exactly api.github.com |
.github.com |
Any subdomain of github.com |
.azmk8s.io |
Any AKS cluster API server |
This action provides input containment: the agent runs inside a locked-down Docker container with network access restricted to an explicit domain allowlist. However, it does not inspect or limit what the agent writes (comments, PRs, file changes). For that you need an output gate.
safe-outputs-action validates constraints (max comments, max PRs), sanitizes secrets, optionally runs AI threat detection, and applies the agent's proposed actions through a controlled write pipeline.
Together the two actions give you full defense-in-depth:
| Layer | Action | What it guards |
|---|---|---|
| Input containment | agent-sandbox-action |
Network access, filesystem, environment |
| Output gate | safe-outputs-action |
Comments, PRs, file writes, secret leakage |
# Full defense-in-depth pipeline for AI agents
# Combines agent-sandbox-action (input containment) with
# safe-outputs-action (output gate)
jobs:
diagnose:
runs-on: ubuntu-latest
permissions:
contents: read
env:
AGENT_ALLOWED_DOMAINS: |
api.githubcopilot.com
api.github.com
.azmk8s.io
login.microsoftonline.com
steps:
- uses: actions/checkout@v5
- uses: microsoftgbb/agent-sandbox-action@v1
with:
command: |
copilot -p "Analyze the cluster diagnostics and produce
findings as agent-output.json following the safe-outputs
schema" --agent cluster-doctor --allow-all-tools
allowed-domains: ${{ env.AGENT_ALLOWED_DOMAINS }}
env-vars: |
GITHUB_TOKEN=${{ secrets.COPILOT_CLI_TOKEN }}
extra-mounts: |
${{ env.HOME }}/.kube/config:/home/agent/.kube/config:ro
- uses: actions/upload-artifact@v4
with:
name: agent-output
path: agent-output.json
scan:
needs: diagnose
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/download-artifact@v4
with:
name: agent-output
- uses: microsoftgbb/safe-outputs-action@v1
with:
artifact-path: agent-output.json
max-comments: 2
max-pull-requests: 1
title-prefix: "[bot] "
threat-detection: true
dry-run: true
- uses: actions/upload-artifact@v4
with:
name: scanned-output
path: agent-output.json
overwrite: true
apply:
needs: [diagnose, scan]
runs-on: ubuntu-latest
permissions:
issues: write
contents: write
pull-requests: write
steps:
- uses: actions/download-artifact@v4
with:
name: scanned-output
- uses: microsoftgbb/safe-outputs-action@v1
with:
artifact-path: agent-output.json
max-comments: 2
max-pull-requests: 1
title-prefix: "[bot] "Job 1 - diagnose: Runs the AI agent inside the sandbox with network access
limited to the domain allowlist. The agent produces agent-output.json.
Job 2 - scan: Downloads the artifact and runs safe-outputs-action in
dry-run mode. This validates constraints, sanitizes secrets, and (optionally)
runs AI threat detection - without writing anything.
Job 3 - apply: If the scan passes, the validated artifact is applied: the action creates comments, PRs, or file changes on behalf of the agent.
This action implements the input containment half of the gh-aw security model. Pair it with safe-outputs-action for the output gate half.
| Layer | gh-aw | agent-sandbox-action |
|---|---|---|
| Container isolation | Docker container | Docker container |
| Network firewall | Squid + iptables (AWF) | Squid + --internal network |
| Domain allowlist | Workflow markdown | Action input (allowed-domains) |
| Audit trail | Internal logging | Proxy access log (action output) |
What this action does NOT do:
- Validate or sanitize agent output (use safe-outputs-action)
- Manage credentials or RBAC (your responsibility)
- Provide AI threat detection (use safe-outputs-action)
The default image (ghcr.io/microsoftgbb/agent-sandbox) includes:
- Ubuntu 24.04
- GitHub Copilot CLI
- kubectl + kubelogin
- Python 3, jq, curl, git
Published to GHCR on every push to main and on version tags.
# Build the agent image locally
docker build -t agent-sandbox:local .
# Test the proxy config
echo "api.github.com" > /tmp/domains.txt
docker run -d --name squid-test \
-v $PWD/proxy/squid.conf:/etc/squid/squid.conf:ro \
-v /tmp/domains.txt:/etc/squid/allowed-domains.txt:ro \
ubuntu/squid:latestMIT