Waybill runs as root in its container SEC-102

Open2 versionsContainers · Medium · Fix · about 30 min ·Linux + Docker

Lab machine

A private Linux machine with Docker Engine. Starting takes about 30 seconds. Sessions last up to 60 minutes.
Priya Raman opened SEC-102 at 10:30SEV-4

The security scan flagged Waybill: root inside the container. Making it non-root broke the event store the first time someone tried.

If an attacker gets code execution in a container that runs as root, a misconfigured mount or a kernel bug becomes a host compromise much more easily. Running as an ordinary user is cheap insurance.

"Last time we just set USER and it broke the event writes. Please also keep /app read-only for the runtime user, the code should not be able to rewrite itself." (Priya)

USER changes who the process runs as. It does not change who owns the files.

Your task

Make the image run as a non-root user, give that user write access to the event store only, keep /app owned by root and read-only to the runtime user, rebuild, and confirm health and an event write and read still work.

On the machine

  • Dockerfile and app/
  • docker run --rm <image> id
  • The event store under /var/lib/waybill

Timeline

Last monthImage scan: "container runs as UID 0".
Last weekSasha adds USER node; Waybill cannot write events and the change is reverted.
10:30SEC-102 reassigned to you.

Done when

  1. The container runs as a user other than root.
  2. Health passes, and an event can be written and read back.
  3. The runtime user cannot write into /app.

Hints

Hint 1

Check the runtime UID, and where the app writes its events (`EVENTS_FILE`, or the code).

Hint 2

Port 8080 needs no privileged bind.

Hint 3

The runtime user needs write access to the event store and nothing else. If the store is inside /app, making it writable makes the code writable.

Hint 4

Set USER in the final stage, and give that user only the state directory, outside /app.

Show the solution

Find where Waybill writes events: `/var/lib/waybill`, or `/app/data` when `EVENTS_FILE` points into the code directory. Keep state outside /app: create `/var/lib/waybill`, `chown` it to the runtime user, point `EVENTS_FILE` there if needed, and set `USER node` in the final stage. Leave `/app` root-owned and read-only. Rebuild and run the validator. `USER` changes who runs; it does not change who owns files.