Skip to content

security(image): remove vscode passwordless-sudo grant - #103

Open
shejnowicz wants to merge 1 commit into
masterfrom
security/12-remove-sudo-grant
Open

security(image): remove vscode passwordless-sudo grant#103
shejnowicz wants to merge 1 commit into
masterfrom
security/12-remove-sudo-grant

Conversation

@shejnowicz

Copy link
Copy Markdown
Collaborator

Closes #12.

Summary

The devcontainers base image ships /etc/sudoers.d/vscode (vscode ALL=(root) NOPASSWD:ALL). Sandcat's agent has no legitimate sudo use — every root-phase step runs in the entrypoint (app-init.sh) before it drops to the vscode user via gosu — so the grant is pure attack surface. This removes it at build time (RUN rm -f /etc/sudoers.d/vscode in Dockerfile.app).

Two-layer defense

Issue #12 had two parts: (1) sandcat's setup must not require sudo — already true (grep of cli/** finds zero sudo usage; the only sudo in the repo is the host-side Docker install instruction in the README), and (2) the user must not be able to sudo inside the image.

Part 2 was partly addressed by #90's runtime security_opt: no-new-privileges, but that's a compose-level knob — the image run bare (docker run -u vscode <agent-image>) still had the grant. This PR closes that gap at the image level:

  • Inside sandcat compose: sudo blocked by two independent layers (removed grant + no-new-privileges).
  • Bare image, outside compose: the removed grant alone denies it.

Test plan

  • regression.bats e2e (real sandcat init → generated project): asserts Dockerfile.app contains rm -f /etc/sudoers.d/vscode. Full test/init/ suite green (131 tests).
  • Hands-on, real containers:
    • Base image control: docker run -u vscode mcr.microsoft.com/devcontainers/base:debian bash -c 'sudo -n whoami'root (exit 0) — the vulnerability the issue reports.
    • Sandcat agent image, entrypoint bypassed: sudo -n whoamisudo: a password is required (exit 1); /etc/sudoers.d/vscode absent; sudo binary still present (no grant = harmless).
    • In-sandbox: sudo -n whoami → blocked by the no-new-privileges message; NoNewPrivs: 1.

Notes

  • The sudo binary is deliberately left installed — removing only the grant means it prompts for a root password that doesn't exist, which is the standard hardened posture. No devcontainer Feature or sandcat runtime step depends on runtime sudo (build-time root work uses USER root in the Dockerfile).

🤖 Generated with Claude Code

https://claude.ai/code/session_01DFCiFbv1Cpr7yzCU8ftvzZ

The devcontainers base image ships /etc/sudoers.d/vscode granting vscode
NOPASSWD:ALL. Sandcat's agent has no legitimate sudo use — every
root-phase step runs in app-init.sh before it drops to vscode via gosu —
so the grant is pure attack surface. Remove it at build time.

This hardens the image itself, complementing the runtime
security_opt: no-new-privileges added in #90: inside sandcat's compose
sudo is now blocked by two independent layers; run outside compose (bare
docker run of the agent image), the removed grant alone denies it.

Verified: base image `docker run -u vscode ... sudo -n whoami` reaches
root; the sandcat agent image (entrypoint bypassed) returns "a password
is required" and the grant file is absent. sudo binary intentionally
left in place (no grant = harmless).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DFCiFbv1Cpr7yzCU8ftvzZ
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.

hardening: Don't use sudo

1 participant