Skip to content

mint: default pid/log paths land in world-writable /tmp with a predictable name #48

Description

@hyperpolymath

What was measured

Hypatia code-scanning alerts 82 and 83 fired on the phase-2 fixture
crates/launcher-common/tests/fixtures/metadata_block/minted-2026-09-23_stapeln-launcher-deed.sh
lines 56–57:

PID_FILE="/tmp/stapeln-server.pid"
LOG_FILE="/tmp/stapeln-server.log"

CodeRabbit/Hypatia anchored this to the fixture, but the fixture is not the defect —
it is a faithful record of what mint emits. Traced to source:

  • crates/launcher-common/src/template.rs:108 — .unwrap_or_else(|| format!("/tmp/{}-server.pid", config.project.name))
  • crates/launcher-common/src/template.rs:113 — .unwrap_or_else(|| format!("/tmp/{}-server.log", config.project.name))

templates/launcher.sh.tera:86-87 merely interpolates {{ pid_file }} / {{ log_file }};
it emits no literal /tmp/. So this is a Rust default, and it reaches every launcher
minted from a config that does not set pid_file/log_file explicitly
— not just this fixture.

Why it matters

The path is both world-writable and fully predictable from the project name. The
generated launcher then acts on that file's contents:

  • templates/launcher.sh.tera:195 — kill -0 "$(cat "$PID_FILE")"
  • :226 — log "Already running (PID $(cat "$PID_FILE"))"
  • :200 — rm -f "$PID_FILE"

so an unprivileged local user can pre-create or symlink /tmp/<name>-server.pid before
first run and influence what the launcher signals or deletes. This is the ordinary
/tmp predictable-name hazard; mktemp-style unpredictability or an XDG-scoped
per-user directory removes it.

Pre-existing, not a phase-2 regression

The legacy fixture minted-2026-09-22_stapeln-launcher.sh carries the same two /tmp/
lines. Phase 2 did not introduce this; the new fixture merely made an existing default visible
to the scanner for the first time. Not a blocker for #46 — filed per the standing rule that
a new scanner finding becomes an issue with acceptance criteria.

Acceptance criteria

  1. The default pid/log location is not a predictable path in a world-writable directory.
    The natural target is $XDG_RUNTIME_DIR (falling back to $XDG_STATE_HOME, then
    ~/.local/state) for the PID file and $XDG_STATE_HOME for the log — per-user, not
    world-writable, and stable across restarts, which mktemp deliberately is not.
  2. An explicit pid_file / log_file in the config still wins, unchanged, including ~
    expansion via expand_home (integration.rs:298-299).
  3. The generated launcher creates the directory if absent, with mode 0700, before writing.
  4. A test asserts the emitted PID_FILE=/LOG_FILE= lines for a config that sets neither
    value, so the default is pinned by a committed artefact rather than by the transform.
    ⚠ Do not assert it by recomputing the same format! in the test — an equality whose right
    side is derived from the left cannot fail when both move.
  5. Both fixtures are re-minted, and Hypatia alerts 82 and 83 close as fixed rather than
    being dismissed.
  6. A note in the config docs states where the default now lands and how to override it.

Out of scope

The three Shellcheck findings on the same generated file — filed separately.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions