You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
These launchers still resolve their PID file through the old launcher-standard ladder:
${XDG_RUNTIME_DIR:-${TMPDIR:-/tmp}}
When XDG_RUNTIME_DIR is unset (cron, su, containers, some SSH sessions, macOS), the PID file lands at a predictable name in world-writable /tmp. This is CWE-377: another local user can pre-create /tmp/<app>-server.pid with a PID of their choosing. is_running() then reports true, and stop kills the attacker's chosen process.
The cure is the ladder that launch-scaffolder main already generates (standards/launcher-standard_praxis.deed, lines 131 and 135). It is now being written into the canonical standard by #1076:
PID_FILE="${XDG_RUNTIME_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}}/launch-scaffolder/<app>/server.pid"
LOG_FILE="${XDG_STATE_HOME:-$HOME/.local/state}/launch-scaffolder/<app>/server.log"
mkdir -p -m 0700 "$(dirname "$PID_FILE")""$(dirname "$LOG_FILE")"# before first write; quote every expansion
Owner ruling A9 applies: the standard follows the generator. Note that the A8 brief wrote the path as <app>/server.pid, without the launch-scaffolder/ segment. The generator's form above, which includes that segment, is authoritative.
Census: 20 launchers (19 live repos + 1 archived)
Every row was re-verified against the repo's origin default branch on 2026-09-30. Line numbers are origin lines, not local ones. "Minted?" means the file carries the generator = "launch-scaffolder" metadata block.
repo
path
line (origin main)
minted by launch-scaffolder?
metadatastician/688-attack-hub
688-attack-hub-launcher.sh
59
yes
metadatastician/boj-server-mk2 ⚠ archived
boj-server-mk2-launcher.sh
59
yes
metadatastician/burble
burble-launcher.sh
69
yes
metadatastician/cadastra
cadastra-launcher.sh
58
yes
metadatastician/cerro-torre
cerro-torre-launcher.sh
58
yes
metadatastician/chronicles-of-slavia
chronicles-of-slavia-launcher.sh
58
yes
metadatastician/enaction-engine
enaction-engine-launcher.sh
58
yes
metadatastician/f117a-stealth-glider
f117a-stealth-glider-launcher.sh
59
yes
metadatastician/f19-stealth-glider
f19-stealth-glider-launcher.sh
59
yes
metadatastician/gossamer
gossamer-launcher.sh
68
yes
metadatastician/paint-type
paint-type-launcher.sh
58
yes
metadatastician/progblocks
progblocks-launcher.sh
59
yes
metadatastician/stapeln
stapeln-launcher.sh
59
yes
metadatastician/universal-modding-studio
idaptik-ums-launcher.sh
59
yes
hyperpolymath/reposystem
total-upgrade/launcher/total-upgrade-launcher.sh
47
no
hyperpolymath/trigger
scripts/trigger-launcher.sh
165 (local runtime_dir=; the PID path is built on line 166)
no
hyperpolymath/valence-shell
launch.sh
44
no
metadatastician/IDApTIK
launcher.sh
68 (RUNTIME_DIR=; PID_FILE= on line 70)
no
metadatastician/IDApTIK
scripts/multiplayer-runtime.sh
31
no
metadatastician/project-ovine
scripts/project-ovine-launcher.sh
24 (RUNTIME_DIR=; PID_FILE= on line 26)
no
Totals: 14 minted (13 live and 1 archived) and 6 hand-written. For each of the three RUNTIME_DIR rows, I confirmed on origin that the variable is used to build the .pid path.
When the census was run, none of these repos had an open PR addressing tmp, XDG, realign or the launcher.
Why 27 became 20
The 2026-09-30 census reported "27 canonical" hits. It counted each repo + path + line once. The 27 rows reduce to 20 as follows:
Deduplicating by repo + path gives 23. The same launcher appeared at different local lines in stale clones (berrywiki, gossamer, stapeln, IDApTIK).
canonical-ums is dropped. Its remote metadatastician/canonical-ums returns 404, so the repo is gone. Two local clones (meta-repos/idaptik-ums-canonical and hyper-repos/metadatastician/canonical-ums) still hold it.
idaptik-ums is folded into universal-modding-studio.metadatastician/idaptik-ums redirects there.
Result: 20.
The GitHub code search for XDG_RUNTIME_DIR in *.sh files under both orgs found no further launchers. It skips archived repos, which is why boj-server-mk2 came only from the local census.
Map each hit to its origin owner/repo via git remote get-url origin.
Deduplicate by repo + path.
Re-check each row against gh api repos/O/R/contents/<path> on the default branch.
The local grep is only the discovery step. The count this issue is judged on is the origin-verified count. A naive re-run will still hit the three stale local copies named above (berrywiki's rescue branch and the two canonical-ums clones). Do not chase those.
Acceptance criteria
Each minted launcher (13 live) is moved to the new ladder by launch-scaffolder realign, landed by PR in its repo.
Each hand-written launcher (6) is moved by a one-line PR to the generator ladder, with mkdir -p -m 0700 of the parent directories before the first write and every $PID_FILE / $LOG_FILE expansion quoted. Note in each PR that realign will not touch the file, because it carries no generator metadata block.
boj-server-mk2 (archived): the owner rules either to unarchive and realign it, or to exempt it from this census. The ruling is recorded here.
A re-run of the census command above, with origin verification, reads 0 non-archived rows, plus boj-server-mk2 resolved per its ruling.
This issue is closed only when that census reads 0. Closing it on "PRs opened" does not count.
What
These launchers still resolve their PID file through the old launcher-standard ladder:
${XDG_RUNTIME_DIR:-${TMPDIR:-/tmp}}When
XDG_RUNTIME_DIRis unset (cron,su, containers, some SSH sessions, macOS), the PID file lands at a predictable name in world-writable/tmp. This is CWE-377: another local user can pre-create/tmp/<app>-server.pidwith a PID of their choosing.is_running()then reports true, andstopkills the attacker's chosen process.The cure is the ladder that launch-scaffolder
mainalready generates (standards/launcher-standard_praxis.deed, lines 131 and 135). It is now being written into the canonical standard by #1076:Owner ruling A9 applies: the standard follows the generator. Note that the A8 brief wrote the path as
<app>/server.pid, without thelaunch-scaffolder/segment. The generator's form above, which includes that segment, is authoritative.Census: 20 launchers (19 live repos + 1 archived)
Every row was re-verified against the repo's origin default branch on 2026-09-30. Line numbers are origin lines, not local ones. "Minted?" means the file carries the
generator = "launch-scaffolder"metadata block.main)688-attack-hub-launcher.shboj-server-mk2-launcher.shburble-launcher.shcadastra-launcher.shcerro-torre-launcher.shchronicles-of-slavia-launcher.shenaction-engine-launcher.shf117a-stealth-glider-launcher.shf19-stealth-glider-launcher.shgossamer-launcher.shpaint-type-launcher.shprogblocks-launcher.shstapeln-launcher.shidaptik-ums-launcher.shtotal-upgrade/launcher/total-upgrade-launcher.shscripts/trigger-launcher.shlocal runtime_dir=; the PID path is built on line 166)launch.shlauncher.shRUNTIME_DIR=;PID_FILE=on line 70)scripts/multiplayer-runtime.shscripts/project-ovine-launcher.shRUNTIME_DIR=;PID_FILE=on line 26)Totals: 14 minted (13 live and 1 archived) and 6 hand-written. For each of the three
RUNTIME_DIRrows, I confirmed on origin that the variable is used to build the.pidpath.When the census was run, none of these repos had an open PR addressing tmp, XDG, realign or the launcher.
Why 27 became 20
The 2026-09-30 census reported "27 canonical" hits. It counted each repo + path + line once. The 27 rows reduce to 20 as follows:
berrywiki-launcher.shwas deleted on originmainin chore(D-16): delete the launcher pair, keep the shellcheck gate it carried metadatastician/berrywiki#51. The localmeta-repos/berrywikicheckout sits on a rescue branch that still has the file.metadatastician/canonical-umsreturns 404, so the repo is gone. Two local clones (meta-repos/idaptik-ums-canonicalandhyper-repos/metadatastician/canonical-ums) still hold it.metadatastician/idaptik-umsredirects there.Result: 20.
The GitHub code search for
XDG_RUNTIME_DIRin*.shfiles under both orgs found no further launchers. It skips archived repos, which is why boj-server-mk2 came only from the local census.How the census was run (the re-run command)
Then:
owner/repoviagit remote get-url origin.gh api repos/O/R/contents/<path>on the default branch.The local grep is only the discovery step. The count this issue is judged on is the origin-verified count. A naive re-run will still hit the three stale local copies named above (berrywiki's rescue branch and the two canonical-ums clones). Do not chase those.
Acceptance criteria
launch-scaffolder realign, landed by PR in its repo.mkdir -p -m 0700of the parent directories before the first write and every$PID_FILE/$LOG_FILEexpansion quoted. Note in each PR that realign will not touch the file, because it carries no generator metadata block.Related
crates/launcher/src/cmd_realign.rs: the realign path for the minted rows.🤖 Generated with Claude Code
https://claude.ai/code/session_0136eszqrQ53Kj7aBH1D4rXK