Skip to content

[WIP] Fix NODE_EXTRA_CA_CERTS path issue after chroot for SSL bump#1552

Closed
Copilot wants to merge 1 commit intomainfrom
copilot/fix-node-extra-ca-certs-issue
Closed

[WIP] Fix NODE_EXTRA_CA_CERTS path issue after chroot for SSL bump#1552
Copilot wants to merge 1 commit intomainfrom
copilot/fix-node-extra-ca-certs-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.


This section details on the original issue you should resolve

<issue_title>[awf] agent-container: NODE_EXTRA_CA_CERTS invalid after chroot breaks ssl-bump TLS trust for Claude Code</issue_title>
<issue_description>## Problem

When --ssl-bump is enabled and --chroot is active, Claude Code (and any Node.js process running inside the chroot) fails to make TLS connections through the Squid proxy because NODE_EXTRA_CA_CERTS points to a path that does not exist after chroot /host.

Symptom observed in the Squid audit log: repeated transaction-end-before-headers failures attributed to client: ::1, with NONE_NONE decisions and 0-byte status. Claude Code exhausts 10 API retries and exits with EHOSTUNREACH. MCP servers and other container-level processes work correctly because they run before the chroot activates and the container's /usr/local/share/ca-certificates/awf-ca.crt is still accessible.

Context

Upstream issue: github/gh-aw#23765 (follow-up from github/gh-aw-firewall#23614).

Reported on:

  • gh-aw CLI v0.65.1
  • AWF container 0.25.5
  • Claude Code CLI 2.1.87

Root Cause

Files involved

  • src/docker-manager.ts lines 962–969 — mounts the per-session CA cert into the agent container at /usr/local/share/ca-certificates/awf-ca.crt and sets NODE_EXTRA_CA_CERTS to that path
  • containers/agent/entrypoint.sh lines 106–119 — calls update-ca-certificates and exports NODE_EXTRA_CA_CERTS="/usr/local/share/ca-certificates/awf-ca.crt"
  • containers/agent/entrypoint.sh lines 724–729 — executes chroot /host /bin/bash -c "...", which changes the filesystem root to the host's /host mount

Why it fails

The CA certificate is a Docker volume mount from the workdir into the container at /usr/local/share/ca-certificates/awf-ca.crt. This path exists on the container's overlay filesystem but is not bind-mounted under /host. After chroot /host, the new root is the host filesystem. Node.js (Claude Code) reads NODE_EXTRA_CA_CERTS and tries to open /usr/local/share/ca-certificates/awf-ca.crt — which is now resolved relative to the host's /, where the AWF CA does not exist.

Squid uses ssl-bump (TLS interception), so after the CONNECT tunnel is established, it presents a dynamically-generated certificate signed by the AWF CA. Because Claude Code cannot load the AWF CA, it rejects the certificate, closes the TLS connection before sending any HTTP headers, and Squid logs transaction-end-before-headers. The client: ::1 label is an artifact of how Squid's ssl-bump internals log the failed inner ssl-bump connection.

Proposed Solution

Apply the same pattern used for one-shot-token.so and get-claude-key.sh (lines 420–474 in entrypoint.sh): copy the CA cert to /host/tmp/awf-lib/ before the chroot activates, then update NODE_EXTRA_CA_CERTS to the chroot-relative path.

In containers/agent/entrypoint.sh, add a block after the get-claude-key.sh copy section (around line 474) and before the capsh check:

# Copy AWF CA certificate to chroot-accessible path for ssl-bump TLS trust
# NODE_EXTRA_CA_CERTS is set to a container path (/usr/local/share/ca-certificates/awf-ca.crt)
# which is NOT accessible after chroot /host. Copy it to /tmp/awf-lib/ (always writable)
# so that Node.js processes (Claude Code, MCP servers) inside the chroot trust the Squid CA.
if [ "\$\{AWF_SSL_BUMP_ENABLED}" = "true" ] && [ -f /usr/local/share/ca-certificates/awf-ca.crt ]; then
  if mkdir -p /host/tmp/awf-lib 2>/dev/null; then
    if cp /usr/local/share/ca-certificates/awf-ca.crt /host/tmp/awf-lib/awf-ca.crt 2>/dev/null; then
      export NODE_EXTRA_CA_CERTS="/tmp/awf-lib/awf-ca.crt"
      echo "[entrypoint] AWF CA certificate copied to chroot at /tmp/awf-lib/awf-ca.crt"
      echo "[entrypoint] NODE_EXTRA_CA_CERTS updated to \$\{NODE_EXTRA_CA_CERTS}"
    else
      echo "[entrypoint][WARN] Could not copy AWF CA certificate to chroot — ssl-bump TLS may fail in chroot"
    fi
  fi
fi

Additionally, to cover non-Node.js tools inside the chroot that rely on the system CA bundle (curl, git, Python requests, etc.), also copy the cert to the host's ca-certificates directory and note that a full update-ca-certificates on the host side is not feasible. For those tools, consider setting SSL_CERT_FILE=/tmp/awf-lib/awf-ca.crt or appending it to the chroot CA bundle (e.g., /etc/ssl/certs/ca-certificates.crt) inside the chroot's /host/etc/ssl/certs/.

The existing CLEANUP_CMD in the chroot exit trap already removes /tmp/awf-lib (line 702), so no extra cleanup is needed.

Also consider adding an integration test that:

  1. Runs with --ssl-bump + chroot mode
  2. Asserts NODE_EXTRA_CA_CERTS resolves to an accessible path after chroot
  3. Validates that curl (alloweddomain/redacted) succeeds without certificate errors

Generated by Firewall Issue Dispatcher ·

<agent_instructions>Create a PR that addresses this issue</agent_instructions>

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

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[awf] agent-container: NODE_EXTRA_CA_CERTS invalid after chroot breaks ssl-bump TLS trust for Claude Code

2 participants