Skip to content

Commit adada80

Browse files
Mossakaclaude
andauthored
fix: create resolv.conf in chroot when not mounted (#549)
* fix: create resolv.conf in chroot when not mounted When using selective /etc mounts in chroot mode, /etc/resolv.conf is not included in the mount list. This causes DNS queries inside the chroot to fall back to the host's systemd-resolved (127.0.0.53), which is blocked by iptables (only 8.8.8.8, 8.8.4.4, 127.0.0.11 are allowed). As a result, agents like Codex cannot resolve domains like api.openai.com. Fix: when /host/etc/resolv.conf doesn't exist, create it from the container's /etc/resolv.conf (which already has the correct AWF DNS config). Clean up on exit by removing the created file. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use curl -f in chroot HTTP blocking test The test used curl -s which silently receives Squid's 403 error page (a valid HTTP response, exit 0). Use curl -f instead, which returns non-zero for HTTP 4xx/5xx responses. This matches the pattern used in the non-chroot integration tests (protocol-support.test.ts). Previously this test only passed because DNS was broken in chroot mode, causing curl to fail at DNS resolution rather than actually testing HTTP blocking behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e2b6482 commit adada80

2 files changed

Lines changed: 24 additions & 7 deletions

File tree

containers/agent/entrypoint.sh

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,28 @@ if [ "${AWF_CHROOT_ENABLED}" = "true" ]; then
162162
# NOTE: We backup the host's original resolv.conf and set up a trap to restore it
163163
RESOLV_BACKUP="/host/etc/resolv.conf.awf-backup-$$"
164164
RESOLV_MODIFIED=false
165-
if cp /host/etc/resolv.conf "$RESOLV_BACKUP" 2>/dev/null; then
166-
if cp /etc/resolv.conf /host/etc/resolv.conf.awf 2>/dev/null; then
167-
mv /host/etc/resolv.conf.awf /host/etc/resolv.conf 2>/dev/null && RESOLV_MODIFIED=true
168-
echo "[entrypoint] DNS configuration copied to chroot (backup at $RESOLV_BACKUP)"
165+
RESOLV_CREATED=false
166+
if [ -f /host/etc/resolv.conf ]; then
167+
# File exists: backup original and replace with AWF DNS configuration
168+
if cp /host/etc/resolv.conf "$RESOLV_BACKUP" 2>/dev/null; then
169+
if cp /etc/resolv.conf /host/etc/resolv.conf.awf 2>/dev/null; then
170+
mv /host/etc/resolv.conf.awf /host/etc/resolv.conf 2>/dev/null && RESOLV_MODIFIED=true
171+
echo "[entrypoint] DNS configuration copied to chroot (backup at $RESOLV_BACKUP)"
172+
else
173+
echo "[entrypoint][WARN] Could not copy DNS configuration to chroot"
174+
fi
169175
else
170-
echo "[entrypoint][WARN] Could not copy DNS configuration to chroot"
176+
echo "[entrypoint][WARN] Could not backup host resolv.conf, skipping DNS override"
171177
fi
172178
else
173-
echo "[entrypoint][WARN] Could not backup host resolv.conf, skipping DNS override"
179+
# File doesn't exist: selective /etc mounts don't include resolv.conf
180+
# Create it from the container's resolv.conf (which has AWF DNS config)
181+
if cp /etc/resolv.conf /host/etc/resolv.conf 2>/dev/null; then
182+
RESOLV_CREATED=true
183+
echo "[entrypoint] DNS configuration created in chroot (/host/etc/resolv.conf)"
184+
else
185+
echo "[entrypoint][WARN] Could not create DNS configuration in chroot"
186+
fi
174187
fi
175188

176189
# Determine working directory inside the chroot
@@ -291,6 +304,10 @@ AWFEOF
291304
CHROOT_RESOLV_BACKUP="${RESOLV_BACKUP#/host}"
292305
CLEANUP_CMD="${CLEANUP_CMD}; mv '${CHROOT_RESOLV_BACKUP}' /etc/resolv.conf 2>/dev/null || true"
293306
echo "[entrypoint] DNS configuration will be restored on exit"
307+
elif [ "$RESOLV_CREATED" = "true" ]; then
308+
# File was created by us; remove it on exit to leave no trace
309+
CLEANUP_CMD="${CLEANUP_CMD}; rm -f /etc/resolv.conf 2>/dev/null || true"
310+
echo "[entrypoint] DNS configuration will be removed on exit"
294311
fi
295312

296313
exec chroot /host /bin/bash -c "

tests/integration/chroot-edge-cases.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ describe('Chroot Edge Cases', () => {
272272
}, 60000);
273273

274274
test('should block HTTP to non-whitelisted domains', async () => {
275-
const result = await runner.runWithSudo('curl -s --connect-timeout 5 http://example.com 2>&1', {
275+
const result = await runner.runWithSudo('curl -f --connect-timeout 5 http://example.com 2>&1', {
276276
allowDomains: ['github.com'],
277277
logLevel: 'debug',
278278
timeout: 30000,

0 commit comments

Comments
 (0)