Installer exposes the enrollment token on the command line, and upgrade reruns leave it valid #92

Open
opened 2026-10-09 15:31:05 -04:00 by goddard · 0 comments
Collaborator

The installer command puts the host's enrollment token on the command line, and the documented upgrade rerun never uses it. Anyone who reads the token within its lifetime can enroll as that host and take over its identity.

  • http.ts:46-49 builds curl … | sudo bash -s -- --controller … --token '<ec_enroll_…>'. The token is in the argv of sudo and bash for the whole install, where any local user can read it from /proc/<pid>/cmdline. sudo's log entry and the admin's shell history keep it too.
  • install.sh:35-36,199-206 runs apt and the Docker install before the token is used at install.sh:251-253. That step writes it to a file to keep it off the agent's command line, but the outer command has already exposed it.
  • ec_agent.py:3125-3131 prints "retaining existing credentials" and returns without contacting the controller when the host is already enrolled. native-hosts.md:175-177 and the deletion blocker at index.ts:96 tell admins to rerun the installer exactly this way, so the token stays valid for its full 15 minutes (index.ts:240).
  • index.ts:323-336 (enrollHost) accepts any valid token, revokes the host's live credential and issues a new one, even while the host is online.

Whoever enrolls with the token receives that host's operations, including instance.create payloads with the RCON password and PLUTO_SERVER_KEY (launch-worker.ts:37-44). The real agent is locked out, and the host still shows as online.

Fix

  • Keep the token out of argv: read it from stdin, /dev/tty or a root-only file
  • Give upgrades a command with no token, or have the agent consume the token when it keeps its existing credential
  • Refuse enrollment for a host with an active credential unless the admin chose re-enroll when generating the token
The installer command puts the host's enrollment token on the command line, and the documented upgrade rerun never uses it. Anyone who reads the token within its lifetime can enroll as that host and take over its identity. - `http.ts:46-49` builds `curl … | sudo bash -s -- --controller … --token '<ec_enroll_…>'`. The token is in the argv of `sudo` and `bash` for the whole install, where any local user can read it from `/proc/<pid>/cmdline`. sudo's log entry and the admin's shell history keep it too. - `install.sh:35-36,199-206` runs apt and the Docker install before the token is used at `install.sh:251-253`. That step writes it to a file to keep it off the agent's command line, but the outer command has already exposed it. - `ec_agent.py:3125-3131` prints "retaining existing credentials" and returns without contacting the controller when the host is already enrolled. `native-hosts.md:175-177` and the deletion blocker at `index.ts:96` tell admins to rerun the installer exactly this way, so the token stays valid for its full 15 minutes (`index.ts:240`). - `index.ts:323-336` (`enrollHost`) accepts any valid token, revokes the host's live credential and issues a new one, even while the host is online. Whoever enrolls with the token receives that host's operations, including `instance.create` payloads with the RCON password and `PLUTO_SERVER_KEY` (`launch-worker.ts:37-44`). The real agent is locked out, and the host still shows as online. **Fix** - [ ] Keep the token out of argv: read it from stdin, `/dev/tty` or a root-only file - [ ] Give upgrades a command with no token, or have the agent consume the token when it keeps its existing credential - [ ] Refuse enrollment for a host with an active credential unless the admin chose re-enroll when generating the token
goddard added the
priority
medium
type/security
labels 2026-10-09 15:31:05 -04:00
josh was assigned by goddard 2026-10-09 15:31:05 -04:00
Sign in to join this conversation.