Summary
scripts/install-systemd-user writes user units with:
WorkingDirectory=$UNIT_ROOT
ExecStart="$PYTHON_BIN" "$ROOT/meter.py"
UNIT_ROOT only substitutes spaces (${ROOT// /\x20}). Newlines, quotes, or backslashes in the clone path can break out of the unit file.
This is user-controlled (you pick the clone directory), not remote injection. Still worth rejecting control characters and quotes in ROOT before interpolating, or generating the unit with a language that escapes systemd strings.
atomic_write_text() in token_meter/app.py also leaves new files at the process umask instead of 0600. The Git-delivery SQLite salt lives under ~/.token-meter/.
Summary
scripts/install-systemd-userwrites user units with:UNIT_ROOTonly substitutes spaces (${ROOT// /\x20}). Newlines, quotes, or backslashes in the clone path can break out of the unit file.This is user-controlled (you pick the clone directory), not remote injection. Still worth rejecting control characters and quotes in
ROOTbefore interpolating, or generating the unit with a language that escapes systemd strings.atomic_write_text()intoken_meter/app.pyalso leaves new files at the process umask instead of0600. The Git-delivery SQLite salt lives under~/.token-meter/.