Skip to content

Commit f84db28

Browse files
docs: sync documentation with recent code changes (#561)
- Update environment.md: Remove HTTP_PROXY/HTTPS_PROXY from internal vars (removed in v0.13.5) - Update chroot-mode.md: Document procfs mounting for Java/dotnet support (added in v0.13.13) - Update usage.md: Document host gateway port restrictions (added in v0.13.13) - Fix AGENTS.md: Correct documentation file references (LOGGING.md → logging_quickref.md) Changes reflect commits from past 7 days including: - 54fd26e: HTTP_PROXY/HTTPS_PROXY removal - dda7c67: procfs mounting for Java/dotnet - 12683ac: Host gateway port restriction Co-authored-by: GitHub Copilot <noreply@github.com>
1 parent 61432e3 commit f84db28

File tree

4 files changed

+61
-21
lines changed

4 files changed

+61
-21
lines changed

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ This is a firewall for GitHub Copilot CLI (package name: `@github/awf`) that pro
1010

1111
- **[README.md](README.md)** - Main project documentation and usage guide
1212
- **[docs/chroot-mode.md](docs/chroot-mode.md)** - Chroot mode for transparent host binary access
13-
- **[LOGGING.md](LOGGING.md)** - Comprehensive logging documentation
1413
- **[docs/logging_quickref.md](docs/logging_quickref.md)** - Quick reference for log queries and monitoring
14+
- **[docs/environment.md](docs/environment.md)** - Environment variable configuration and security best practices
1515

1616
## Development Workflow
1717

docs/chroot-mode.md

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,14 @@ iptables rules applied (redirect HTTP/HTTPS to Squid)
5656
If AWF_CHROOT_ENABLED=true:
5757
5858
1. Verify capsh exists on host
59-
2. Copy DNS configuration to /host/etc/resolv.conf
60-
3. Map host user by UID
61-
4. Write command to temp script with PATH setup
62-
5. chroot /host
63-
6. Drop capabilities (CAP_NET_ADMIN, CAP_SYS_CHROOT)
64-
7. Switch to host user
65-
8. Execute command
59+
2. Mount container-scoped procfs at /host/proc (for Java/dotnet)
60+
3. Copy DNS configuration to /host/etc/resolv.conf
61+
4. Map host user by UID
62+
5. Write command to temp script with PATH setup
63+
6. chroot /host
64+
7. Drop capabilities (CAP_NET_ADMIN, CAP_SYS_CHROOT, CAP_SYS_ADMIN)
65+
8. Switch to host user
66+
9. Execute command
6667
6768
All child processes inherit chroot environment
6869
All HTTP/HTTPS traffic → Squid proxy → Domain filtering
@@ -79,6 +80,32 @@ All HTTP/HTTPS traffic → Squid proxy → Domain filtering
7980
| PATH | Container PATH | Reconstructed for host binaries |
8081
| Network isolation | iptables → Squid | iptables → Squid (unchanged) |
8182

83+
### Procfs Mounting for Java and .NET
84+
85+
As of v0.13.13, chroot mode mounts a fresh container-scoped procfs at `/host/proc` to support Java and .NET runtimes:
86+
87+
**Why this is needed:**
88+
- Java's JVM requires access to `/proc/cpuinfo` for CPU detection
89+
- .NET's CLR requires `/proc/self/exe` to resolve the runtime binary path
90+
- Static bind mounts of `/proc/self` always resolve to the parent shell, not the current process
91+
92+
**How it works:**
93+
1. Before chroot, the entrypoint mounts a fresh procfs: `mount -t proc -o nosuid,nodev,noexec proc /host/proc`
94+
2. This requires `CAP_SYS_ADMIN` capability, which is granted during container startup
95+
3. The procfs is container-scoped, showing only container processes (not host processes)
96+
4. `CAP_SYS_ADMIN` is dropped via capsh before executing user commands
97+
98+
**Security implications:**
99+
- The mounted procfs only exposes container processes, not host processes
100+
- Mount operation completes before user code runs (capability dropped)
101+
- procfs is mounted with security restrictions: `nosuid,nodev,noexec`
102+
- User code cannot unmount or remount (no `CAP_SYS_ADMIN`, umount blocked in seccomp)
103+
104+
**Backwards compatibility:**
105+
- Existing code continues to work without changes
106+
- Java and .NET commands now succeed in chroot mode (previously failed with cryptic errors)
107+
- No impact on non-chroot mode
108+
82109
## Usage
83110

84111
### Basic Usage
@@ -164,7 +191,8 @@ In chroot mode, selective paths are mounted for security instead of the entire f
164191
| `/etc/ca-certificates` | `/host/etc/ca-certificates:ro` | CA certificates |
165192
| `/etc/passwd` | `/host/etc/passwd:ro` | User lookup |
166193
| `/etc/group` | `/host/etc/group:ro` | Group lookup |
167-
| `/proc/self` | `/host/proc/self:ro` | Process self-info (needed by Go) |
194+
195+
**Note:** As of v0.13.13, `/proc` is no longer bind-mounted. Instead, a fresh container-scoped procfs is mounted at `/host/proc` during entrypoint initialization. This provides dynamic `/proc/self/exe` resolution required by Java and .NET runtimes.
168196

169197
### Read-Write Mounts
170198

@@ -190,10 +218,13 @@ The container starts with capabilities needed for setup, then drops them before
190218
|------------|--------------|---------------------|---------|
191219
| `CAP_NET_ADMIN` | Granted | **Dropped** | iptables setup, then prevented |
192220
| `CAP_SYS_CHROOT` | Granted | **Dropped** | Entrypoint chroot, then prevented |
221+
| `CAP_SYS_ADMIN` | Granted (chroot mode) | **Dropped** | procfs mount for Java/dotnet, then prevented |
193222
| `CAP_NET_RAW` | Denied | Denied | Prevents raw socket bypass |
194223
| `CAP_SYS_PTRACE` | Denied | Denied | Prevents process debugging |
195224
| `CAP_SYS_MODULE` | Denied | Denied | Prevents kernel module loading |
196225

226+
**Note:** `CAP_SYS_ADMIN` is only granted in chroot mode (v0.13.13+) for mounting procfs. It's dropped immediately after mount completes, before user commands run.
227+
197228
After capability drop, the process has:
198229
```
199230
CapInh: 0000000000000000

docs/environment.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ awf --env-all 'command'
1717

1818
When using `sudo -E`, these host variables are automatically passed: `GITHUB_TOKEN`, `GH_TOKEN`, `GITHUB_PERSONAL_ACCESS_TOKEN`, `USER`, `TERM`, `HOME`, `XDG_CONFIG_HOME`.
1919

20-
The following are always set/overridden: `HTTP_PROXY`, `HTTPS_PROXY` (Squid proxy), `PATH` (container values).
20+
The following are always set/overridden: `PATH` (container values).
2121

2222
Variables from `--env` flags override everything else.
2323

24+
**Note:** As of v0.13.5, `HTTP_PROXY` and `HTTPS_PROXY` are no longer automatically set. Traffic is transparently redirected to Squid via iptables NAT rules. If needed, you can still set these manually with `--env HTTP_PROXY=...`
25+
2426
## Security Warning: `--env-all`
2527

2628
Using `--env-all` passes all host environment variables to the container, which creates security risks:
@@ -30,7 +32,9 @@ Using `--env-all` passes all host environment variables to the container, which
3032
3. **Unnecessary Access**: Extra variables increase attack surface (violates least privilege)
3133
4. **Accidental Sharing**: Easy to forget what's in your environment when sharing commands
3234

33-
**Excluded variables** (even with `--env-all`): `PATH`, `PWD`, `OLDPWD`, `SHLVL`, `_`, `SUDO_*`
35+
**Excluded variables** (even with `--env-all`): `PATH`, `PWD`, `OLDPWD`, `SHLVL`, `_`, `SUDO_*`, `HTTP_PROXY`, `HTTPS_PROXY`, `http_proxy`, `https_proxy`, `NO_PROXY`, `no_proxy`
36+
37+
**Proxy variables:** Host proxy settings are excluded to prevent conflicts with iptables-based traffic redirection. The firewall uses transparent proxying via iptables NAT rules instead of environment variable-based proxy configuration.
3438

3539
## Best Practices
3640

@@ -58,13 +62,14 @@ The following environment variables are set internally by the firewall and used
5862
| Variable | Description | Example |
5963
|----------|-------------|---------|
6064
| `AWF_DNS_SERVERS` | Comma-separated list of trusted DNS servers | `8.8.8.8,8.8.4.4` |
61-
| `HTTP_PROXY` | Squid proxy URL for HTTP traffic | `http://172.30.0.10:3128` |
62-
| `HTTPS_PROXY` | Squid proxy URL for HTTPS traffic | `http://172.30.0.10:3128` |
63-
| `SQUID_PROXY_HOST` | Squid container hostname | `squid-proxy` |
64-
| `SQUID_PROXY_PORT` | Squid proxy port | `3128` |
65+
| `AWF_CHROOT_ENABLED` | Whether chroot mode is enabled | `true` |
66+
| `AWF_HOST_PATH` | Host PATH passed to chroot environment | `/usr/local/bin:/usr/bin` |
67+
| `NO_PROXY` | Domains bypassing Squid (host access mode) | `localhost,host.docker.internal` |
6568

6669
**Note:** These are set automatically based on CLI options and should not be overridden manually.
6770

71+
**Historical note:** Prior to v0.13.5, `HTTP_PROXY` and `HTTPS_PROXY` were set to point to Squid. These have been removed in favor of transparent iptables-based redirection, which is more reliable and avoids conflicts with tools that don't honor proxy environment variables.
72+
6873
## Troubleshooting
6974

7075
**Variable not accessible:** Use `sudo -E` or pass explicitly with `--env VAR="$VAR"`

docs/usage.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -322,12 +322,13 @@ sudo awf \
322322

323323
### Security Considerations
324324

325-
> ⚠️ **Security Warning**: When `--enable-host-access` is combined with `host.docker.internal` in `--allow-domains`, containers can access **ANY service** running on the host machine, including:
326-
> - Local databases (PostgreSQL, MySQL, Redis)
327-
> - Development servers
328-
> - Other sensitive services
325+
> ⚠️ **Security Warning**: When `--enable-host-access` is enabled, containers can access services running on the host machine via `host.docker.internal`.
329326
>
330-
> Only enable this for trusted workloads like MCP gateways.
327+
> **Port restrictions:** As of v0.13.13+, access is restricted to ports 80, 443, and any ports specified with `--allow-host-ports`. This prevents access to arbitrary services like databases, admin panels, etc.
328+
>
329+
> **Before v0.13.13:** All ports were accessible when host access was enabled, creating a security risk.
330+
>
331+
> Only enable this for trusted workloads like MCP gateways or local testing with Playwright.
331332

332333
**Why opt-in?** By default, `host.docker.internal` hostname resolution is disabled to prevent containers from accessing host services. This is a defense-in-depth measure against malicious code attempting to access local resources.
333334

@@ -337,13 +338,16 @@ sudo awf \
337338
# Start your MCP gateway on the host (port 8080)
338339
./my-mcp-gateway --port 8080 &
339340
340-
# Run awf with host access enabled
341+
# Run awf with host access enabled and custom port
341342
sudo awf \
342343
--enable-host-access \
344+
--allow-host-ports 8080 \
343345
--allow-domains host.docker.internal,api.github.com \
344346
-- 'copilot --mcp-gateway http://host.docker.internal:8080 --prompt "test"'
345347
```
346348

349+
**Note:** Ports 80 and 443 are always allowed when `--enable-host-access` is enabled. Use `--allow-host-ports` to allow additional ports (e.g., for MCP gateways or development servers running on non-standard ports).
350+
347351
### CONNECT Method on Port 80
348352

349353
The firewall allows the HTTP CONNECT method on both ports 80 and 443. This is required because some HTTP clients (e.g., Node.js fetch) use the CONNECT method even for HTTP connections when going through a proxy. Domain ACLs remain the primary security control.

0 commit comments

Comments
 (0)