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

    priority:p1High - schedule nextscope:repoConfined to this repositorysecuritySecurity posture, secrets, scanning, advisories, supply chain

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions