Repository navigation
Security model
To report a vulnerability, see SECURITY.md.
-
Read-only host access. The bot reads
/proc,/sys, the Unraidemhttpdirectory,config.toml, and the helper socket directory through read-only mounts. It writes only to its own/datavolume and to an in-memory/tmp. -
Locked-down containers. Compose starts two containers,
shazzzbotanddocker-proxy. Each has a read-only root filesystem, no Linux capabilities, andno-new-privileges. The bot runs as user id10001, and the proxy runs asroot. The bot has a limit of 512 MB of memory and 128 processes. The proxy has a limit of 128 MB and 64 processes. Docker keeps at most three 10 MB log files for each container. -
Docker proxy allowlist. The bot never touches the Docker socket. It talks to
docker-proxy, an HAProxy container that permits three requests only:-
GET /containers/json(list containers). -
GET /info(engine information). -
POST /containers/<id>/restart(restart one container). The id or name must start with a letter or a digit.
Each path can start with an API version, for example
/v1.47. The proxy refuses every other request with403. The proxy has no published port, so only containers on the Compose network can reach it. -
-
Deny by default. A command runs only for a role or user listed in a tier that allows it. It also runs only in the configured server, and only in an output channel or in
commands_channel_id. Only/aboutis open to all users. -
Confirm and audit. A restart needs a click on Confirm. The bot posts each change to the audit channel with a mention of the person who made it. The mention does not ping.
-
Fail closed. If the audit channel is not set or the bot cannot see it,
/charts window,/blowup,/update, and all/dockercommands refuse to run. A restart also stops when its audit post fails. -
[restarts] allow. The/dockercommands accept only containers that match a pattern in[restarts] allow, also for a group from[restarts.groups]. The default empty list turns restarts off (see Restarts). -
Host helper. The optional Host helper runs as
rootand serves fixed reads over a Unix socket. It keeps its files in one private directory on a pool. Each request needs a signature made with a shared key. The bot sends only thehello,tasks, andups_shutdownactions. -
Pinned relay. The bot checks the certificate of each relay against
RELAY_FINGERPRINTbefore it sends the key. The relay accepts only TLS 1.3 (see Relay). -
Secrets in the environment. The Discord token, the Jellyfin key, the helper key, the relay keys, and the forge tokens come from environment variables. They are not in
config.toml(see Environment variables). -
Pinned dependencies.
Dockerfileandcompose.yamlpin the Python and HAProxy images by digest.requirements.txtlocks each Python package, and the image build checks the hash of each package.setup.shchecks each helper file against the SHA-256 in the release.
Warning
The docker-proxy container mounts the Docker socket, and access to that socket is equal to root access on the server. Do not publish its port 2375 and do not add rules to docker-proxy/haproxy.cfg unless you understand each new request.