Config file is stored in the publicly served directory in Docker #8

Closed
opened 2026-10-12 14:29:33 +02:00 by pepa · 0 comments
Owner

Security issue. Found while reviewing the app for hosting many customers as one container per customer.

Problem

  • Dockerfile starts the app with CMD ["/app/rezervator", "-c /app/target/site/data/config.toml"].
  • src/main.rs serves the whole site root as static files: .service(Files::new("/", site_root)), and the site root is target/site.

So the configuration file is expected at target/site/data/config.toml, which is inside the static file root. Anything in target/site/data/ is reachable under /data/ (that is how /data/banner.css is loaded), so the config should be downloadable at /data/config.toml without authentication. It contains the database password, the session signing key and the SMTP credentials.

This follows from the code; it has not been tried against a running container yet.

With the session key an attacker can forge a session cookie for any user, including an admin.

Suggested fix

  • Read the config from a path outside the site root, e.g. /app/config/config.toml (mounted as a volume or a Docker secret), and update Dockerfile accordingly.
  • Keep target/site/data only for files that are meant to be public (banner image, generated CSS).
  • Consider allowing the secrets (database password, session key, SMTP password) to come from environment variables.
  • Existing deployments must rotate the session key and the database and SMTP passwords after the fix, since they may have been exposed.

Done when

  • GET /data/config.toml returns 404 in a container built from Dockerfile.
  • The app starts with the config mounted outside the site root.
  • README describes where the config file goes.
Security issue. Found while reviewing the app for hosting many customers as one container per customer. ## Problem - `Dockerfile` starts the app with `CMD ["/app/rezervator", "-c /app/target/site/data/config.toml"]`. - `src/main.rs` serves the whole site root as static files: `.service(Files::new("/", site_root))`, and the site root is `target/site`. So the configuration file is expected at `target/site/data/config.toml`, which is inside the static file root. Anything in `target/site/data/` is reachable under `/data/` (that is how `/data/banner.css` is loaded), so the config should be downloadable at `/data/config.toml` without authentication. It contains the database password, the session signing key and the SMTP credentials. This follows from the code; it has not been tried against a running container yet. With the session key an attacker can forge a session cookie for any user, including an admin. ## Suggested fix - Read the config from a path outside the site root, e.g. `/app/config/config.toml` (mounted as a volume or a Docker secret), and update `Dockerfile` accordingly. - Keep `target/site/data` only for files that are meant to be public (banner image, generated CSS). - Consider allowing the secrets (database password, session key, SMTP password) to come from environment variables. - Existing deployments must rotate the session key and the database and SMTP passwords after the fix, since they may have been exposed. ## Done when - `GET /data/config.toml` returns 404 in a container built from `Dockerfile`. - The app starts with the config mounted outside the site root. - README describes where the config file goes.
pepa closed this issue 2026-10-12 15:05:14 +02:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ITsolved/rezervovator#8