Skip to content

Project VMs grant the deploy user root-equivalent NOPASSWD:ALL, masking the fine-grained env/deploy sudoers #165

Description

@samo-agent

Summary

On shared-web project VMs, the deploy/app user (the account samohost SSHes in as to build, deploy, and manage apps) is granted a root-equivalent catch-all sudo rule — effectively <deploy-user> ALL=(ALL) NOPASSWD:ALL — via a cloud-init-generated sudoers drop-in. This catch-all silently overrides and nullifies the fine-grained, per-command sudoers rules that samohost's own provisioning (buildHostPrepScript / bootstrap) carefully emits for the env/deploy paths.

Net effect: those least-privilege grants become security theater. They enumerate exactly which commands the deploy user should be allowed to run as root, but because a broader NOPASSWD:ALL rule already covers everything, the enumeration constrains nothing. The deploy user can run any command as root regardless of what the fine-grained files say.

Why this is a real problem (not just cosmetic)

  1. Blast radius. A compromise (or a bug) in any deploy-time command runs as root on the VM, defeating the entire point of scoping the deploy user's privileges. The hardening story ("deploy runs least-privilege") is false in effective posture.

  2. It masks real coverage gaps. Because everything "just works" under the catch-all, missing entries in the fine-grained sudoers go undetected. Concretely, during recent shared-web preview work a sudo -u ... tee step that writes an app config file appeared to work — but it only worked because of the catch-all. On a properly-hardened VM (deploy user scoped to just the enumerated commands) that step would have been denied. So the catch-all is actively hiding places where the real sudoers is incomplete, and those gaps will surface as failures the first time a VM is hardened correctly.

Recommendation

  • Scope the deploy user's sudo to the specific commands samohost actually needs — the env/deploy sudoers samohost already emits enumerate them, so the allowed set is already known.
  • Drop the cloud-init NOPASSWD:ALL catch-all on project VMs (and retrofit existing ones).
  • Add an audit/doctor check that fails when the deploy user has a broad NOPASSWD:ALL (or otherwise root-equivalent) grant, so a re-introduced catch-all is caught rather than silently trusted.
  • Once the catch-all is gone, re-run the deploy/preview flows to surface (and fill) any fine-grained sudoers gaps that the catch-all was masking (e.g. the config-file tee step above).

Then the least-privilege grants samohost emits are real, and the "deploy runs least-privilege" claim actually holds.

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions