Icecast ships a default source password of "hackme" in three places #3

Closed
opened 2026-08-20 03:06:26 -04:00 by logan · 1 comment
Owner

hackme is the default Icecast source password in all three places a node can pick one up:

File Line
docker-compose.yml ICECAST_SOURCE_PASSWORD: ${ICECAST_SOURCE_PASSWORD:-hackme}
setup.sh read -rsp "Source password [hackme]: " — pressing Enter accepts it
.env.example ICECAST_SOURCE_PASSWORD=hackme

drb-edge-node/app/config.py carries the same default (icecast_source_password: str = "hackme").

Icecast binds all interfaces, so on a node whose operator pressed Enter through setup.sh anyone on that LAN can push audio into the node's stream — the stream the frontend and mobile clients play as live traffic. For a public-safety product, an unauthenticated party being able to inject audio into what users believe is live radio is the part that matters, more than the eavesdropping.

Carried over from the 2026-08-05/06 security audit, which listed it as an open HIGH and where it has sat since.

Fix direction: generate a random source password during setup.sh instead of offering a default, and drop the :-hackme fallback in compose so a missing value fails loudly rather than silently becoming a known credential. Related but separate: node-26#1, where the dashboard is still on its first-boot default in the field.

Rotating this on node-002 is an operational step, not just a code change.

`hackme` is the default Icecast source password in all three places a node can pick one up: | File | Line | |---|---| | `docker-compose.yml` | `ICECAST_SOURCE_PASSWORD: ${ICECAST_SOURCE_PASSWORD:-hackme}` | | `setup.sh` | `read -rsp "Source password [hackme]: "` — pressing Enter accepts it | | `.env.example` | `ICECAST_SOURCE_PASSWORD=hackme` | `drb-edge-node/app/config.py` carries the same default (`icecast_source_password: str = "hackme"`). Icecast binds all interfaces, so on a node whose operator pressed Enter through `setup.sh` anyone on that LAN can push audio into the node's stream — the stream the frontend and mobile clients play as live traffic. For a public-safety product, an unauthenticated party being able to inject audio into what users believe is live radio is the part that matters, more than the eavesdropping. Carried over from the 2026-08-05/06 security audit, which listed it as an open HIGH and where it has sat since. Fix direction: generate a random source password during `setup.sh` instead of offering a default, and drop the `:-hackme` fallback in compose so a missing value fails loudly rather than silently becoming a known credential. Related but separate: node-26#1, where the dashboard is still on its first-boot default in the field. Rotating this on node-002 is an operational step, not just a code change.
logan closed this issue 2026-08-20 03:12:47 -04:00
Author
Owner

Fixed in e6aab75.

Every fallback is gone rather than replaced with a better default:

  • icecast/entrypoint.sh refuses to start if either password is empty and prints how to generate one. This is the single hard gate.
  • docker-compose.yml uses ${VAR:?message}, so a missing value stops the stack at compose time instead of becoming an empty string.
  • setup.sh now generates a random password when the operator presses Enter (openssl rand -base64 24, /dev/urandom fallback). That is the real behaviour change — a prompt default nobody types over is not a default, it is the value.
  • .env.example ships both keys empty with the generation command in a comment; README.md marks them required with no default.
  • drb-edge-node/app/config.py and op25-container/app/main.py no longer carry hackme either.

Client suite: 185 passed.

Still outstanding, and it is the part that actually protects node-002: the deployed node's .env has whatever it was set up with. Nothing here rotates it. Generate a new one on the node with openssl rand -base64 24, put it in .env, and restart the stack.

Also added .gitattributes pinning *.sh to LF (fb13bb8) — git warned that entrypoint.sh would become CRLF in the Windows working copy, and a CRLF shebang inside a Linux container fails as bad interpreter: /bin/sh^M, which shows up only as a container that will not start.

Fixed in `e6aab75`. Every fallback is gone rather than replaced with a better default: - `icecast/entrypoint.sh` refuses to start if either password is empty and prints how to generate one. This is the single hard gate. - `docker-compose.yml` uses `${VAR:?message}`, so a missing value stops the stack at compose time instead of becoming an empty string. - `setup.sh` now **generates** a random password when the operator presses Enter (`openssl rand -base64 24`, `/dev/urandom` fallback). That is the real behaviour change — a prompt default nobody types over is not a default, it is the value. - `.env.example` ships both keys empty with the generation command in a comment; `README.md` marks them required with no default. - `drb-edge-node/app/config.py` and `op25-container/app/main.py` no longer carry `hackme` either. Client suite: 185 passed. **Still outstanding, and it is the part that actually protects node-002:** the deployed node's `.env` has whatever it was set up with. Nothing here rotates it. Generate a new one on the node with `openssl rand -base64 24`, put it in `.env`, and restart the stack. Also added `.gitattributes` pinning `*.sh` to LF (`fb13bb8`) — `git` warned that `entrypoint.sh` would become CRLF in the Windows working copy, and a CRLF shebang inside a Linux container fails as `bad interpreter: /bin/sh^M`, which shows up only as a container that will not start.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: logan/node-26#3