Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 22, 2026

Mount host filesystem as read-only for improved security. Add isolate.sh utility to run host binaries via chroot when not available in container PATH.

Changes

  • Read-only host mount: Changed default mount from /:/host:rw to /:/host:ro in docker-manager.ts. The /:/host:ro mount is now always included regardless of whether custom volume mounts are specified, ensuring chroot functionality is always available.
  • isolate.sh script: Added to agent container at /usr/local/bin/isolate.sh
    • Falls back to chroot into /host when binary not found in container PATH
    • Handles both absolute paths and relative commands
    • Validates /host exists before chroot attempt
  • Automatic command wrapping: Modified entrypoint.sh to wrap all user commands with isolate.sh, making it the execution gateway for all commands in the container

Usage

All commands in the container now automatically run through isolate.sh. If a binary exists in the container PATH, it runs directly. Otherwise, it chroots into /host and executes there.

# Commands are automatically wrapped - no manual invocation needed
# Example: if python3 is not in container but exists on host, it will be found via chroot
python3 script.py

# Direct invocation still works
isolate.sh /usr/bin/custom-tool --flag
Original prompt

Mount host / to /host as readonly in the firewall, and add a ./isolate.sh script to chroot jail the commands into /root if the binary is not in PATH


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits January 22, 2026 22:52
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Copilot AI changed the title [WIP] Add isolate script for chroot jail in firewall feat: mount host / as readonly and add isolate.sh script Jan 22, 2026
Copilot AI requested a review from Mossaka January 22, 2026 22:55
@Mossaka Mossaka marked this pull request as ready for review January 22, 2026 22:56
@github-actions
Copy link

github-actions bot commented Jan 22, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link

github-actions bot commented Jan 22, 2026

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@Mossaka
Copy link
Collaborator

Mossaka commented Jan 22, 2026

@copilot how to force that every command running in this container would be wrapped with ./isolate.sh?

@github-actions
Copy link

github-actions bot commented Jan 22, 2026

⚠️ Coverage Regression Detected

This PR decreases test coverage. Please add tests to maintain coverage levels.

Overall Coverage

Metric Base PR Delta
Lines 77.88% 77.63% 📉 -0.25%
Statements 77.94% 77.71% 📉 -0.23%
Functions 77.29% 77.54% 📈 +0.25%
Branches 71.00% 70.39% 📉 -0.61%
📁 Per-file Coverage Changes (2 files)
File Lines (Before → After) Statements (Before → After)
src/docker-manager.ts 79.1% → 79.3% (+0.19%) 78.4% → 78.6% (+0.19%)
src/cli.ts 35.5% → 35.9% (+0.38%) 35.5% → 36.2% (+0.62%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

Copy link
Contributor Author

Copilot AI commented Jan 22, 2026

@copilot how to force that every command running in this container would be wrapped with ./isolate.sh?

To force all commands through isolate.sh, modify the entrypoint.sh (line 144) to wrap commands:

exec capsh --drop=cap_net_admin -- -c "exec gosu awfuser /usr/local/bin/isolate.sh $(printf '%q ' "$@")"

This would make isolate.sh the execution gateway for all user commands, automatically falling back to host binaries via chroot when not found in container PATH.

Would you like me to implement this change?

@github-actions
Copy link

Claude Smoke Test Results

Last 2 Merged PRs:

  • Improve links in readme to AW project
  • mossaka/log filtering

Test Results:

  • ✅ GitHub MCP: Retrieved PRs successfully
  • ✅ Playwright: Page title verified ("GitHub · Change is constant. GitHub keeps you ahead. · GitHub")
  • ✅ File Write: Created /tmp/gh-aw/agent/smoke-test-claude-21267812435.txt
  • ✅ Bash: File verified with cat

Status: PASS

AI generated by Smoke Claude

@github-actions
Copy link

Smoke Test Results - Copilot

✅ GitHub MCP: Retrieved last 2 merged PRs (#388, #387)
✅ Playwright: Verified GitHub page title contains "GitHub"
✅ File Writing: Created smoke test file at /tmp/gh-aw/agent/smoke-test-copilot-21267812411.txt
✅ Bash Tool: Successfully verified file creation

Status: PASS 🎉

cc: @Copilot @Mossaka

AI generated by Smoke Copilot

@github-actions
Copy link

Security Review: Critical Concerns with isolate.sh chroot implementation

This PR introduces a significant security risk by allowing arbitrary host binary execution via chroot /host. While the change from read-write to read-only mount (/:/host:ro) is a security improvement, it does not adequately mitigate the risks introduced by the chroot functionality.


🔴 Critical Issue 1: Setuid Binary Privilege Escalation

File: containers/agent/isolate.sh (lines 48, 64)

Problem: Host binaries with the setuid bit can be executed via isolate.sh, potentially allowing privilege escalation even though the container runs as non-root awfuser.

Code:

exec chroot /host "$COMMAND" "$@"

Risk: The read-only mount does not prevent setuid execution. Host binaries like /usr/bin/sudo, /usr/bin/pkexec, or custom setuid binaries can be invoked:

isolate.sh /usr/bin/sudo -l  # May expose sudo configuration
isolate.sh /usr/bin/pkexec <command>  # PolicyKit exploitation vector

Mitigation Required: Use nosuid mount option to prevent setuid execution:

// In src/docker-manager.ts line 361
agentVolumes.unshift('/:/host:ro,nosuid');

🔴 Critical Issue 2: File Capabilities Bypass Container Restrictions

File: containers/agent/isolate.sh (lines 48, 64)

Problem: Host binaries with file capabilities (e.g., CAP_NET_RAW, CAP_NET_ADMIN) retain those capabilities even when executed from the container, bypassing the container's capability dropping.

Example:

# If host ping has CAP_NET_RAW file capability
isolate.sh /usr/bin/ping  # Bypasses container's cap_drop: ['NET_RAW']

Risk: This undermines the security hardening in src/docker-manager.ts:387-393 where capabilities are explicitly dropped.

Mitigation Required:

  1. Add nosuid mount option (also strips file capabilities)
  2. Or block chroot syscall entirely via seccomp

🟡 Medium Issue 3: Attack Surface Expansion

File: containers/agent/isolate.sh (entire file)

Problem: Exposes all host system binaries (potentially thousands) to execution within the container, dramatically increasing the attack surface.

Risk:

  • Host may have vulnerable binaries (e.g., ImageMagick, FFmpeg, older utilities)
  • Host shared libraries (/lib, /usr/lib) may have vulnerabilities
  • Many binaries were never designed for sandboxed execution

Example Attack Vectors:

isolate.sh /usr/bin/convert malicious.jpg out.png  # ImageMagick RCE
isolate.sh /usr/bin/ffmpeg -i video.mp4  # FFmpeg exploits

Recommended Actions

Option 1: Prevent chroot (Recommended)

  1. Drop CAP_SYS_CHROOT capability in src/docker-manager.ts:387:

    cap_drop: [
      'NET_RAW',
      'SYS_PTRACE',
      'SYS_MODULE',
      'SYS_RAWIO',
      'MKNOD',
      'SYS_CHROOT',  // ADD THIS
    ],
  2. Block chroot syscall in containers/agent/seccomp-profile.json:

    {
      "names": ["chroot"],
      "action": "SCMP_ACT_ERRNO",
      "errnoRet": 1,
      "comment": "Block chroot to prevent host binary execution"
    }
  3. Remove isolate.sh script entirely

Option 2: Harden chroot (If truly needed)

  1. Add nosuid mount option:

    agentVolumes.unshift('/:/host:ro,nosuid');
  2. Implement binary whitelisting in isolate.sh

  3. Add explicit path validation to prevent arbitrary binary execution


Why Read-Only Mount is Insufficient

The read-only mount prevents:

  • ✅ Writing to host filesystem
  • ✅ Creating new files on host

But does not prevent:

  • ❌ Setuid binary execution
  • ❌ File capability inheritance
  • ❌ Exploitation of vulnerable host binaries
  • ❌ Network exfiltration from host binaries

Recommendation: I strongly recommend Option 1 (blocking chroot entirely) unless there's a compelling use case that requires host binary execution. The security risks outweigh the convenience benefits.

cc @Mossaka for security review

AI generated by Security Guard

@Mossaka
Copy link
Collaborator

Mossaka commented Jan 23, 2026

@copilot yes implement: exec capsh --drop=cap_net_admin -- -c "exec gosu awfuser /usr/local/bin/isolate.sh $(printf '%q ' "$@")"

Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 23, 2026

@copilot yes implement: exec capsh --drop=cap_net_admin -- -c "exec gosu awfuser /usr/local/bin/isolate.sh $(printf '%q ' "$@")"

Implemented in commit 5c12927. All commands in the container now run through isolate.sh, automatically falling back to host binaries via chroot when not found in container PATH.

@Mossaka
Copy link
Collaborator

Mossaka commented Jan 23, 2026

@copilot modify the firewall so that even if custom mounts are added, the /host is still mounted as ro

Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 23, 2026

@copilot modify the firewall so that even if custom mounts are added, the /host is still mounted as ro

Implemented in commit 8945204. The /:/host:ro mount is now always included regardless of whether custom mounts are specified, ensuring chroot functionality is always available.

@github-actions
Copy link

github-actions bot commented Jan 23, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link

github-actions bot commented Jan 23, 2026

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions
Copy link

Smoke Test Results (Claude)

✅ GitHub MCP: PASS
✅ Playwright: PASS (title: "GitHub · Change is constant. GitHub keeps you ahead. · GitHub")
✅ File Write: PASS
✅ Bash: PASS

Overall Status: PASS

AI generated by Smoke Claude

@github-actions
Copy link

Smoke Test Results ✅ PASS

Last 2 Merged PRs:

Test Results:

  • ✅ GitHub MCP - Retrieved PR data
  • ✅ Playwright - Title contains "GitHub"
  • ✅ File Write - Created test file
  • ✅ Bash Tool - Verified file content

cc @Copilot @Mossaka

AI generated by Smoke Copilot

@github-actions
Copy link

🚨 Security Review: Critical Concerns Identified

I've reviewed this PR and identified significant security concerns that weaken the firewall's security posture. While the read-only host mount is an improvement, the isolate.sh chroot mechanism introduces serious risks.


⚠️ Critical Issue #1: Container Isolation Bypass via Chroot

File: containers/agent/isolate.sh (lines 47, 63)
Code:

exec chroot /host "$COMMAND" "$@"

Security Impact:
The script allows arbitrary execution of ANY binary from the host filesystem by chrooting into /host. This fundamentally breaks container isolation, which is a core security boundary.

Risks:

  • Privilege escalation potential: Host binaries may have setuid/setgid bits, capabilities, or other privileges that don't exist in the container
  • Bypass security controls: Host binaries may not be subject to the same seccomp profiles, capability restrictions, or resource limits as container binaries
  • Expanded attack surface: An attacker who compromises the agent now has access to ALL host binaries, not just container binaries
  • Unexpected behavior: Host binaries may behave differently than expected when run via chroot (different libraries, configurations, etc.)

Example attack scenario:
If the host has a vulnerable or misconfigured binary (e.g., an old version of curl with a known CVE), an attacker could exploit it by triggering the chroot fallback.


⚠️ Critical Issue #2: Automatic Transparent Fallback

File: containers/agent/entrypoint.sh (line 145)
Code:

exec capsh --drop=cap_net_admin -- -c "exec gosu awfuser /usr/local/bin/isolate.sh $(printf '%q ' "$@")"

Security Impact:
ALL user commands are now automatically wrapped with isolate.sh, enabling invisible chroot fallback to host binaries.

Risks:

  • No user consent: Users have no way to know when they're executing host binaries vs container binaries
  • No opt-out mechanism: This behavior is forced on all commands with no way to disable it
  • Violates least privilege: The firewall should restrict access, not expand it by giving access to all host binaries

Example attack scenario:
A malicious AI agent could craft commands that intentionally trigger the fallback (e.g., using binaries not in the container) to access host resources or exploit host-specific vulnerabilities.


⚠️ Issue #3: Security Context Differences

File: containers/agent/isolate.sh (lines 62-63)
Code:

if chroot /host which "$COMMAND" >/dev/null 2>&1; then
  exec chroot /host "$COMMAND" "$@"

Security Impact:
The script uses which inside the chroot to check if commands exist, which itself executes host code.

Risks:

  • Trusted command exploitation: If which or shell on the host is compromised, this check could be exploited
  • Different PATH resolution: Host PATH may include directories not intended for container access

📋 Recommendations

  1. Do not merge this PR without addressing the security concerns

  2. Consider alternative approaches:

    • Explicit allow-list: Only allow specific host binaries via a curated allow-list (not arbitrary chroot)
    • Container image extension: Include necessary binaries in the container image instead of relying on host
    • Explicit opt-in: Require users to explicitly request chroot functionality (not automatic fallback)
    • Sandboxing: If chroot is necessary, add additional sandboxing (AppArmor, SELinux, seccomp-bpf for chroot'd processes)
  3. Security review required:

    • Threat modeling: What attack scenarios does this enable?
    • Penetration testing: Can an attacker exploit this to break out of the firewall?
    • Principle review: Does this align with the firewall's security goals?

🔒 Security Principle Violation

The AWF firewall is designed to restrict network access for AI agents while maintaining filesystem access. This PR fundamentally changes the security model by:

  • Expanding execution scope: From container binaries → all host binaries
  • Breaking isolation: Containers should be isolated from the host
  • Violating least privilege: Users should only get the access they need

The read-only mount (/:/host:ro) does NOT adequately mitigate these risks because:

  • Execution of host binaries can still access host resources (memory, processes, network)
  • Read-only prevents file modification but not code execution
  • Host binaries may have capabilities or privileges that bypass read-only restrictions

Verdict:Do not merge - This PR introduces critical security vulnerabilities that weaken the firewall's security posture.

AI generated by Security Guard

@Mossaka
Copy link
Collaborator

Mossaka commented Jan 26, 2026

Closing PR to reduce backlog. Created issue #420 to track this work. Will fix it later.

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.

2 participants