Repository navigation
[BUG]Sandbox container hangs in an infinite certutil password-retry loop when restarted #1498
Description
Summary
The sandbox container's entrypoint (containers/docker-entrypoint.sh) hangs forever after the container is restarted. On restart, certutil -N runs against an already-initialized NSS database and tries to prompt for the database password, but a detached container has no TTY. The failed read is treated as an invalid password, so NSS retries in a tight loop, producing endless log spam and ~100% CPU on one core. The script never proceeds past this point, so the CA trust import (certutil -A) is skipped and the container is left half-initialized.
Environment
- STRIX version: 1.3.0 (sandbox image
ghcr.io/usestrix/strix-sandbox:1.3.0) - OS: Windows 10 (Docker Desktop,
desktop-linuxcontext) - Docker Engine: 29.8.2
- Also verified that
main(containers/docker-entrypoint.sh) still has the same unguardedcertutil -Ncall.
Steps to reproduce
- Start a STRIX session so the sandbox container is created and initialized. The first run succeeds:
certutil -N -d sql:/home/pentester/.pki/nssdb --empty-passwordcreates a fresh, empty-password NSS DB. - Stop the sandbox container (e.g.
docker stop, restarting Docker Desktop, or a host reboot). - Start the same container again (
docker start/ Docker Desktop UI). - The entrypoint re-runs and hangs at the
certutil -Nstep.
Expected behavior
The entrypoint should be idempotent: restarting the container should reuse the existing NSS DB and finish initialization.
Actual behavior
docker logs fills with this pair of lines (hundreds of times per second, indefinitely):
Error opening input terminal for read
Invalid password. Try again.
Error opening input terminal for read
Invalid password. Try again.
...
docker top shows the stuck process, running for the entire container uptime:
root sudo -u pentester certutil -N -d sql:/home/pentester/.pki/nssdb --empty-password
pentester certutil -N -d sql:/home/pentester/.pki/nssdb --empty-password
docker stats shows ~102% CPU. Because the script is set -e and certutil never exits, everything after this line never runs on restart, including:
sudo -u pentester certutil -A -n "Testing Root CA" -t "C,," -i /app/certs/ca.crt -d sql:/home/pentester/.pki/nssdb
So the sandbox comes up with Caido running but without the testing CA in the browser trust store, which breaks HTTPS interception for any session that reuses it.
Root cause
NSS certutil -N only short-circuits the password prompt (via --empty-password) when it creates a fresh database. When cert9.db/key4.db already exist, certutil -N instead asks for the existing DB password through the NSS password callback. With no controlling terminal, the read fails ("Error opening input terminal for read"), the empty input is treated as a wrong password, and the callback retries forever.
This is a known NSS pitfall — mkcert hit the identical loop and worked around it by checking for the DB's existence before calling certutil -N: FiloSottile/mkcert#558
Suggested fix
Guard the initialization with an existence check, mirroring mkcert's approach:
sudo -u pentester mkdir -p /home/pentester/.pki/nssdb
if [ ! -f /home/pentester/.pki/nssdb/cert9.db ]; then
sudo -u pentester certutil -N -d sql:/home/pentester/.pki/nssdb --empty-password
fi
sudo -u pentester certutil -A -n "Testing Root CA" -t "C,," -i /app/certs/ca.crt -d sql:/home/pentester/.pki/nssdb(The certutil -A re-import is safe to repeat — it overwrites the entry with the same nickname.)
Workaround
Remove and recreate the sandbox instead of restarting it:
docker rm -f <sandbox-container>The next STRIX session creates a fresh sandbox whose first-run initialization succeeds.
Activity