Skip to content

[SEC] F-02: remove the updater sidecar and the Update button - #121

Merged
ustoppble merged 3 commits into
mainfrom
sec-updater
Nov 4, 2026
Merged

ustoppble merged 3 commits into
mainfrom
sec-updater

Conversation

@ustoppble

Copy link
Copy Markdown
Owner

Why

Audit finding F-02 (critical): the updater sidecar ran as root, mounted /var/run/docker.sock, the writable checkout and the host /tmp, installed packages at boot and ran deploy/deploy.sh. Compromise it and you own the host. Owner's decision: turn the button off; updating is only cd /opt/overclick && ./deploy/deploy.sh on the host.

What goes

  • updater service, update-trigger volume and UPDATE_TRIGGER_DIR from deploy/docker-compose.cloud.yml and docker-compose.yml.
  • App: triggerUpdateAction, readUpdaterStateAction, the heartbeat/status/trigger readers in lib/updates.ts, updaterEnableCommand, the Update button and its polling in the Updates tab and in the new-version banner, plus the i18n strings (pt-BR and en). No orphaned action or route is left; a test greps the app for the removed names.
  • The banner and Updates tab still show the running version, the newer release when the check is on, and the command to run on the server.

What the deploy does on the server

deploy.sh removes the old updater container (found by its compose labels, never by touching app or the db) before building, and after up --remove-orphans removes the leftover overclick_update-trigger volume only if no container uses it. App is recreated as on any deploy; the data volume is untouched. The first deploy of this change must run on the host, not from the old button (it would remove its own runner). Documented in deploy/README.md; quickstart users get --remove-orphans on their update command.

Left as is (decision needed)

The source-checkout flow (runSourceUpdateAction, update mode auto: git pull + pnpm install in the app's own process) does not use the sidecar and is not in F-02, so it stays. It is also an in-app update button, but only outside containers; say if it should go too.

Verification

pnpm typecheck, pnpm build, pnpm test (web 1516 passed), scripts/test-deploy-project-files.sh (extended with the sidecar/volume cases). check:sheet needs a live seeded board with a session; not run (unrelated to this diff).

🤖 Generated with Claude Code

ustoppble and others added 2 commits November 4, 2026 18:42
The updater ran as root with the docker socket, a writable checkout and the
host /tmp, and ran deploy.sh: compromise it, own the host. Updating is now only
./deploy/deploy.sh on the host.

- compose (cloud and root): updater service, trigger volume and UPDATE_TRIGGER_DIR gone
- deploy.sh: removes the retired updater container (by compose label) and its
  trigger volume; app and database are never named
- app: no trigger/poll actions, no heartbeat reader; banner and Updates tab show
  the version and the command to run on the server (pt-BR and en)
- docs and tests adjusted

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…command, in every runtime

The source runtime still showed Update now / Force update and called
runSourceUpdateAction, a server action that ran git pull, install, build and
restart from the web process. Removed the action and the UI (and the strings and
stale volume/Dockerfile notes that went with them). The page tells the version
and the command to run on the server.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@ustoppble
ustoppble changed the base branch from main to sec-infra November 4, 2026 21:47
@ustoppble
ustoppble changed the base branch from sec-infra to main November 4, 2026 22:50
@ustoppble
ustoppble merged commit 88bab42 into main Nov 4, 2026
1 check passed
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.

1 participant