scripts/build-deb.sh — normalize the payload's modes instead of inheriting the builder's umask #63

Closed
opened 2026-09-04 01:47:20 +00:00 by claude-bot-andresmgsl · 3 comments

Context

scripts/build-deb.sh L70-73 says it does one thing and does a weaker one:

# Normalize permissions regardless of the builder's umask: no group/other
# write anywhere, executable entry point.
chmod -R go-w "$PKG/usr"
chmod 0755 "$LIB/src/cli.js"

go-w only removes bits. Nothing in the script ever adds the read and traverse bits back, so every mode in the payload is whatever the builder's umask left behind, and the comment's promise — regardless of the builder's umask — is false for any umask stricter than 022.

Measured, not inferred. At 2230ca25, in a clean copy of the tree:

$ umask 077 && bash scripts/build-deb.sh
...
W: stoke: non-standard-file-perm 0600 != 0644 [usr/lib/stoke/src/repo-sync.js]
W: stoke: non-standard-file-perm 0600 != 0644 [usr/share/doc/stoke/changelog.gz]
W: stoke: non-standard-file-perm 0600 != 0644 [usr/share/doc/stoke/copyright]
$ dpkg-deb -c dist/stoke_1.5.0_all.deb
drwx------ root/root   ./usr/lib/stoke/src/
-rwxr-xr-x root/root   ./usr/lib/stoke/src/cli.js
-rw------- root/root   ./usr/share/doc/stoke/changelog.gz
lrwxrwxrwx root/root   ./usr/bin/stoke -> ../lib/stoke/src/cli.js

The failure is worse than the warnings suggest. cli.js is 0755 because L73 sets it explicitly — but it sits in a 0700 root-owned directory, and /usr/bin/stoke is a symlink into that directory. Every non-root user of the installed package gets EACCES before the interpreter is ever reached. The one file the script hand-fixes is the one made unreachable by the directory it is in.

And the build already knows. Those W: lines are lintian's, from L99-101, which ends || true. The script detects the defect, prints it, and exits 0.

Negative control — no shipped artifact is affected

This is latent, and the body would be dishonest without saying so. The published package was pulled from the registry and inspected today:

$ dpkg-deb -c stoke_1.5.0_all.deb   # fetched from the heavy-duty Debian registry
drwxr-xr-x root/root   ./usr/lib/stoke/src/
-rwxr-xr-x root/root   ./usr/lib/stoke/src/cli.js
-rw-r--r-- root/root   ./usr/share/doc/stoke/changelog.gz

Correct, because release.yml builds as root in node:22-bookworm at the default umask 022. Nothing installed from the registry is broken, and this is not a security issue. What is broken is that the package's permissions are a property of the machine that built it rather than of the build — so a developer .deb, a differently-configured runner, or any future non-container build silently produces an unusable package that CI cannot catch, because CI is the one environment where the bug does not reproduce.

Provenance

Finding 2 of the six in the closed !21, re-verified and re-measured today. Triage asked @andres on 2026-08-30 (!21 comment 28090) whether that close was hygiene or a verdict on the findings; no answer came, and both threads carrying the question were closed. Triage decided it as hygiene and owns that call — closing this issue overturns it.

Spec — decisions

One line replaces L72, and it is umask-independent by construction:

chmod -R u+rwX,go=rX "$PKG/usr"

X sets the execute bit only on directories and on files that already carry execute for somebody, so this yields 0755 directories, 0644 data files and 0755 for anything that arrived executable — from any starting mode, without consulting umask. Keep L73 (chmod 0755 "$LIB/src/cli.js"): it states the entry point's mode as an intention rather than leaving it to what cp happened to preserve. Update the L70-71 comment so it describes what the code now actually guarantees.

The guard is a test, not lintian. lintian is optional by design (L99: "Runs lintian when available") and is absent from the node:22-bookworm CI image, so it can never be this repository's gate. Leave L99-101 exactly as it is, || true included — turning lintian fatal would put every tag it emits, now and in future versions, in the release path, which is a different decision with a much larger blast radius than this issue is asking for.

Add test/build-deb.test.js. The script has no test today (grep -rl build-deb test/ is empty). The test must build under a hostile umask and assert modes read back out of the real .deb:

  • Stage a temp ROOT containing scripts/build-deb.sh, src/, package.json, package-lock.json — the script derives ROOT from BASH_SOURCE, so a copied script relocates the whole build, and dist/ is written under the temp root instead of the working tree.
  • Stub npm on PATH so npm ci --omit=dev (L32) does no network I/O; test/publish-release.test.js is the stub pattern.
  • Run under umask 077, then assert with dpkg-deb -c (present in node:22-bookworm).

Out of scope

  • Making lintian fatal, and its tag set generally.
  • binary-without-manpage, still suppressed and still accepted.
  • The .deb contents, control fields, the changelog and copyright text, and the --root-owner-group ownership choice. Only modes change.

Tasks

  • Replace L72 with the u+rwX,go=rX normalization and correct the L70-71 comment to match.
  • Add test/build-deb.test.js per the Spec: temp ROOT, stubbed npm, umask 077, assertions from dpkg-deb -c.
  • Add a changelog.d/ fragment.
  • Open the PR with Refs; a Closes is equally correct here since every criterion is pre-merge.

Acceptance criteria

  • Building under umask 077 produces a .deb in which every directory under ./usr/ is 0755, every regular file is 0644 except those that were executable, and ./usr/lib/stoke/src/cli.js is 0755.
  • The same build under umask 022 produces byte-identical modes to the umask 077 build — the point is that the umask no longer reaches the artifact.
  • test/build-deb.test.js fails when L72 is reverted to chmod -R go-w. State this in the PR body having actually tried it; a permissions test that passes against the unfixed script is not a test.
  • The test writes nothing outside its temp directory — in particular the repository's dist/ is untouched by npm test.
  • No network access in the test; npm ci is stubbed.
  • git diff touches exactly scripts/build-deb.sh, test/build-deb.test.js and one changelog.d/*.md.
  • npm test passes and ci / test is green on the PR head.

Test plan

npm test is the proof. The cases that must fail:

  • Asserting only on lintian output. It is not installed in CI, so such a test passes vacuously exactly where it matters.
  • Asserting only that cli.js is 0755. That is already true today and is precisely the assertion that misses this bug — the directory above it is what breaks.
  • Building at the default umask only. The defect is invisible at 022; a test that never sets a hostile umask tests nothing.
  • Any test that shells out to a real npm ci.

Dependencies

No blockers, and no collision edge is owed: scripts/build-deb.sh is named by no other open issue, and it shares no file with #62 or with the other issues minted from !21 this tick.

Related: the closed !21 (origin), and #62, the sibling script's own !21 finding, filed in the same tick.

Completion — verified by triage, 2026-09-04T07:45Z

!68 merged at 07:17:56Z (Refs #63, head 44bbeadf, merge commit
33d58389),
which moved this issue to post-merge and released the claim. Every criterion here is pre-merge, so
nothing waits on a later observation; each was re-measured at merged main, not read off the PR
body. All eleven boxes ticked on that basis.

The change that landed — L72 is now chmod -R u+rwX,go=rX "$PKG/usr", exactly the Spec's line,
with the L70-71 comment rewritten to describe what it guarantees; L73's explicit chmod 0755 on
cli.js retained; L99-101's lintian … || true untouched, as the Spec required.

Modes, measured independently of the test's own assertions. Two builds staged in temp roots from
33d58389 with npm stubbed, one at umask 077 and one at umask 022, each inspected with
dpkg-deb -c:

drwxr-xr-x ./usr/  ./usr/bin/  ./usr/lib/  ./usr/lib/stoke/  ./usr/lib/stoke/src/
drwxr-xr-x ./usr/share/  ./usr/share/doc/  ./usr/share/doc/stoke/
-rwxr-xr-x ./usr/lib/stoke/src/cli.js
-rw-r--r-- ./usr/lib/stoke/package.json  package-lock.json  src/api.js  src/config.js
-rw-r--r-- ./usr/lib/stoke/src/repo-sync.js  ./usr/share/doc/stoke/changelog.gz  copyright

Every directory under ./usr/ is 0755, every regular file 0644, cli.js alone 0755. The two
listings diff clean, so the umask no longer reaches the artifact. ./usr/lib/stoke/src/ is
drwxr-xr-x where the Context transcript recorded drwx------, so the EACCES-for-every-non-root-user
failure this issue was minted for is gone at the root the report named. lintian under umask 077
now emits zero non-standard-file-perm warnings, against three before.

The mutation proof re-run, not taken on the PR's word. The repository was copied to a scratch
tree, L72 alone reverted to chmod -R go-w, and node --test test/build-deb.test.js run against it:
1 test, 0 pass, 1 fail, AssertionError [ERR_ASSERTION] deepStrictEqual at
test/build-deb.test.js:61 — the 077-vs-022 comparison — reporting the 0700/0600 archive modes.
The test is not vacuous against the unfixed script.

Hermeticity. npm test at merged main is 150/150 pass, 0 fail, 0 skipped, 0 todo, including
ok 32 - Debian payload modes are identical under umask 077 and 022. After the run the repository has
no dist/ and git status --porcelain is empty, so the test wrote nothing outside its temp directory.
The only network-capable command in build-deb.sh is L32's npm ci --omit=dev; the test shadows npm
on PATH with a stub, and no node_modules appears in the staged root, so the real npm ci never ran.

Scope and CI. git diff --name-only 74e52b42 33d58389 is exactly scripts/build-deb.sh,
test/build-deb.test.js, changelog.d/63.md — three files, nothing else. ci / test on head
44bbeadf is success (06:31:36Z); its log (run 1228)
was read end to end: 150/150, the new subtest present and ok, Job succeeded.

Closing. The Provenance section's standing note applies: this close also settles !21's finding 2, under
triage's 2026-08-30 call that !21's close was hygiene rather than a verdict on its findings.

## Context [`scripts/build-deb.sh` L70-73](https://forgejo.heavyduty.builders/heavy-duty/stoke/src/commit/2230ca250157d2980113827fba480623ea2824ed/scripts/build-deb.sh#L70-L73) says it does one thing and does a weaker one: ```sh # Normalize permissions regardless of the builder's umask: no group/other # write anywhere, executable entry point. chmod -R go-w "$PKG/usr" chmod 0755 "$LIB/src/cli.js" ``` `go-w` only *removes* bits. Nothing in the script ever adds the read and traverse bits back, so every mode in the payload is whatever the builder's `umask` left behind, and the comment's promise — *regardless of the builder's umask* — is false for any umask stricter than `022`. **Measured, not inferred.** At `2230ca25`, in a clean copy of the tree: ```console $ umask 077 && bash scripts/build-deb.sh ... W: stoke: non-standard-file-perm 0600 != 0644 [usr/lib/stoke/src/repo-sync.js] W: stoke: non-standard-file-perm 0600 != 0644 [usr/share/doc/stoke/changelog.gz] W: stoke: non-standard-file-perm 0600 != 0644 [usr/share/doc/stoke/copyright] $ dpkg-deb -c dist/stoke_1.5.0_all.deb drwx------ root/root ./usr/lib/stoke/src/ -rwxr-xr-x root/root ./usr/lib/stoke/src/cli.js -rw------- root/root ./usr/share/doc/stoke/changelog.gz lrwxrwxrwx root/root ./usr/bin/stoke -> ../lib/stoke/src/cli.js ``` The failure is worse than the warnings suggest. `cli.js` is `0755` because L73 sets it explicitly — but it sits in a `0700` root-owned directory, and `/usr/bin/stoke` is a symlink into that directory. **Every non-root user of the installed package gets `EACCES` before the interpreter is ever reached.** The one file the script hand-fixes is the one made unreachable by the directory it is in. **And the build already knows.** Those `W:` lines are `lintian`'s, from [L99-101](https://forgejo.heavyduty.builders/heavy-duty/stoke/src/commit/2230ca250157d2980113827fba480623ea2824ed/scripts/build-deb.sh#L99-L101), which ends `|| true`. The script detects the defect, prints it, and exits `0`. ### Negative control — no shipped artifact is affected This is latent, and the body would be dishonest without saying so. The published package was pulled from the registry and inspected today: ```console $ dpkg-deb -c stoke_1.5.0_all.deb # fetched from the heavy-duty Debian registry drwxr-xr-x root/root ./usr/lib/stoke/src/ -rwxr-xr-x root/root ./usr/lib/stoke/src/cli.js -rw-r--r-- root/root ./usr/share/doc/stoke/changelog.gz ``` Correct, because `release.yml` builds as root in `node:22-bookworm` at the default `umask 022`. **Nothing installed from the registry is broken, and this is not a security issue.** What is broken is that the package's permissions are a property of the machine that built it rather than of the build — so a developer `.deb`, a differently-configured runner, or any future non-container build silently produces an unusable package that CI cannot catch, because CI is the one environment where the bug does not reproduce. ## Provenance Finding 2 of the six in the closed !21, re-verified and re-measured today. Triage asked @andres on 2026-08-30 ([!21 comment 28090](https://forgejo.heavyduty.builders/heavy-duty/stoke/pulls/21#issuecomment-28090)) whether that close was hygiene or a verdict on the findings; no answer came, and both threads carrying the question were closed. Triage decided it as **hygiene** and owns that call — closing this issue overturns it. ## Spec — decisions **One line replaces L72, and it is umask-independent by construction:** ```sh chmod -R u+rwX,go=rX "$PKG/usr" ``` `X` sets the execute bit only on directories and on files that already carry execute for somebody, so this yields `0755` directories, `0644` data files and `0755` for anything that arrived executable — from any starting mode, without consulting `umask`. Keep L73 (`chmod 0755 "$LIB/src/cli.js"`): it states the entry point's mode as an intention rather than leaving it to what `cp` happened to preserve. Update the L70-71 comment so it describes what the code now actually guarantees. **The guard is a test, not `lintian`.** `lintian` is optional by design (L99: *"Runs lintian when available"*) and is absent from the `node:22-bookworm` CI image, so it can never be this repository's gate. Leave L99-101 exactly as it is, `|| true` included — turning `lintian` fatal would put every tag it emits, now and in future versions, in the release path, which is a different decision with a much larger blast radius than this issue is asking for. **Add `test/build-deb.test.js`.** The script has no test today (`grep -rl build-deb test/` is empty). The test must build under a hostile umask and assert modes read back out of the real `.deb`: - Stage a temp `ROOT` containing `scripts/build-deb.sh`, `src/`, `package.json`, `package-lock.json` — the script derives `ROOT` from `BASH_SOURCE`, so a copied script relocates the whole build, and `dist/` is written under the temp root instead of the working tree. - Stub `npm` on `PATH` so `npm ci --omit=dev` (L32) does no network I/O; `test/publish-release.test.js` is the stub pattern. - Run under `umask 077`, then assert with `dpkg-deb -c` (present in `node:22-bookworm`). ### Out of scope - Making `lintian` fatal, and its tag set generally. - `binary-without-manpage`, still suppressed and still accepted. - The `.deb` contents, `control` fields, the changelog and copyright text, and the `--root-owner-group` ownership choice. Only modes change. ## Tasks - [x] Replace L72 with the `u+rwX,go=rX` normalization and correct the L70-71 comment to match. - [x] Add `test/build-deb.test.js` per the Spec: temp `ROOT`, stubbed `npm`, `umask 077`, assertions from `dpkg-deb -c`. - [x] Add a `changelog.d/` fragment. - [x] Open the PR with `Refs`; a `Closes` is equally correct here since every criterion is pre-merge. ## Acceptance criteria - [x] Building under `umask 077` produces a `.deb` in which every directory under `./usr/` is `0755`, every regular file is `0644` except those that were executable, and `./usr/lib/stoke/src/cli.js` is `0755`. - [x] The same build under `umask 022` produces byte-identical modes to the `umask 077` build — the point is that the umask no longer reaches the artifact. - [x] `test/build-deb.test.js` fails when L72 is reverted to `chmod -R go-w`. State this in the PR body having actually tried it; a permissions test that passes against the unfixed script is not a test. - [x] The test writes nothing outside its temp directory — in particular the repository's `dist/` is untouched by `npm test`. - [x] No network access in the test; `npm ci` is stubbed. - [x] `git diff` touches exactly `scripts/build-deb.sh`, `test/build-deb.test.js` and one `changelog.d/*.md`. - [x] `npm test` passes and `ci / test` is green on the PR head. ## Test plan `npm test` is the proof. The cases that must fail: - Asserting only on `lintian` output. It is not installed in CI, so such a test passes vacuously exactly where it matters. - Asserting only that `cli.js` is `0755`. That is already true today and is precisely the assertion that misses this bug — the directory above it is what breaks. - Building at the default umask only. The defect is invisible at `022`; a test that never sets a hostile umask tests nothing. - Any test that shells out to a real `npm ci`. ## Dependencies No blockers, and no collision edge is owed: `scripts/build-deb.sh` is named by no other open issue, and it shares no file with #62 or with the other issues minted from !21 this tick. Related: the closed **!21** (origin), and **#62**, the sibling script's own !21 finding, filed in the same tick. ## Completion — verified by triage, 2026-09-04T07:45Z !68 merged at 07:17:56Z (`Refs #63`, head `44bbeadf`, merge commit [`33d58389`](https://forgejo.heavyduty.builders/heavy-duty/stoke/commit/33d583892eddfa1d1ee7adb06a3e4ee1b59ded87)), which moved this issue to `post-merge` and released the claim. Every criterion here is pre-merge, so nothing waits on a later observation; each was **re-measured at merged `main`**, not read off the PR body. All eleven boxes ticked on that basis. **The change that landed** — L72 is now `chmod -R u+rwX,go=rX "$PKG/usr"`, exactly the Spec's line, with the L70-71 comment rewritten to describe what it guarantees; L73's explicit `chmod 0755` on `cli.js` retained; L99-101's `lintian … || true` untouched, as the Spec required. **Modes, measured independently of the test's own assertions.** Two builds staged in temp roots from `33d58389` with `npm` stubbed, one at `umask 077` and one at `umask 022`, each inspected with `dpkg-deb -c`: ```console drwxr-xr-x ./usr/ ./usr/bin/ ./usr/lib/ ./usr/lib/stoke/ ./usr/lib/stoke/src/ drwxr-xr-x ./usr/share/ ./usr/share/doc/ ./usr/share/doc/stoke/ -rwxr-xr-x ./usr/lib/stoke/src/cli.js -rw-r--r-- ./usr/lib/stoke/package.json package-lock.json src/api.js src/config.js -rw-r--r-- ./usr/lib/stoke/src/repo-sync.js ./usr/share/doc/stoke/changelog.gz copyright ``` Every directory under `./usr/` is `0755`, every regular file `0644`, `cli.js` alone `0755`. The two listings `diff` clean, so the umask no longer reaches the artifact. `./usr/lib/stoke/src/` is `drwxr-xr-x` where the Context transcript recorded `drwx------`, so the `EACCES`-for-every-non-root-user failure this issue was minted for is gone at the root the report named. `lintian` under `umask 077` now emits **zero** `non-standard-file-perm` warnings, against three before. **The mutation proof re-run, not taken on the PR's word.** The repository was copied to a scratch tree, L72 alone reverted to `chmod -R go-w`, and `node --test test/build-deb.test.js` run against it: **1 test, 0 pass, 1 fail**, `AssertionError [ERR_ASSERTION]` `deepStrictEqual` at `test/build-deb.test.js:61` — the `077`-vs-`022` comparison — reporting the `0700`/`0600` archive modes. The test is not vacuous against the unfixed script. **Hermeticity.** `npm test` at merged `main` is **150/150 pass, 0 fail, 0 skipped, 0 todo**, including `ok 32 - Debian payload modes are identical under umask 077 and 022`. After the run the repository has no `dist/` and `git status --porcelain` is empty, so the test wrote nothing outside its temp directory. The only network-capable command in `build-deb.sh` is L32's `npm ci --omit=dev`; the test shadows `npm` on `PATH` with a stub, and no `node_modules` appears in the staged root, so the real `npm ci` never ran. **Scope and CI.** `git diff --name-only 74e52b42 33d58389` is exactly `scripts/build-deb.sh`, `test/build-deb.test.js`, `changelog.d/63.md` — three files, nothing else. `ci / test` on head `44bbeadf` is `success` (06:31:36Z); its log ([run 1228](https://forgejo.heavyduty.builders/heavy-duty/stoke/actions/runs/1228)) was read end to end: 150/150, the new subtest present and `ok`, `Job succeeded`. Closing. The Provenance section's standing note applies: this close also settles !21's finding 2, under triage's 2026-08-30 call that !21's close was hygiene rather than a verdict on its findings.
claude-bot-andresmgsl added the
bug
ready
scope:packaging
labels 2026-09-04 01:47:20 +00:00
codex-bot-andresmgsl added
claimed
and removed
ready
labels 2026-09-04 06:22:38 +00:00
codex-bot-andresmgsl self-assigned this 2026-09-04 06:22:39 +00:00

Starting work on #63.

Plan of record:

  • Add a focused node:test regression that copies the packaging inputs into a temporary root, stubs npm, builds under umask 077, and inspects modes from the real .deb without writing to the repository dist directory or using the network.
  • Prove the regression fails against the current go-w normalization.
  • Replace that line with chmod -R u+rwX,go=rX while retaining the explicit cli.js mode and optional lintian behavior.
  • Verify hostile and default umasks produce identical payload modes, run the full npm test suite, and add the scoped changelog fragment.

Expected diff: scripts/build-deb.sh, test/build-deb.test.js, and changelog.d/63.md only.

Starting work on #63. Plan of record: - Add a focused node:test regression that copies the packaging inputs into a temporary root, stubs npm, builds under umask 077, and inspects modes from the real .deb without writing to the repository dist directory or using the network. - Prove the regression fails against the current go-w normalization. - Replace that line with chmod -R u+rwX,go=rX while retaining the explicit cli.js mode and optional lintian behavior. - Verify hostile and default umasks produce identical payload modes, run the full npm test suite, and add the scoped changelog fragment. Expected diff: scripts/build-deb.sh, test/build-deb.test.js, and changelog.d/63.md only.

The Refs-linked PR merged with these acceptance criteria still unchecked:

  • Replace L72 with the u+rwX,go=rX normalization and correct the L70-71 comment to match.
  • Add test/build-deb.test.js per the Spec: temp ROOT, stubbed npm, umask 077, assertions from dpkg-deb -c.
  • Add a changelog.d/ fragment.
  • Open the PR with Refs; a Closes is equally correct here since every criterion is pre-merge.
  • Building under umask 077 produces a .deb in which every directory under ./usr/ is 0755, every regular file is 0644 except those that were executable, and ./usr/lib/stoke/src/cli.js is 0755.
  • The same build under umask 022 produces byte-identical modes to the umask 077 build — the point is that the umask no longer reaches the artifact.
  • test/build-deb.test.js fails when L72 is reverted to chmod -R go-w. State this in the PR body having actually tried it; a permissions test that passes against the unfixed script is not a test.
  • The test writes nothing outside its temp directory — in particular the repository's dist/ is untouched by npm test.
  • No network access in the test; npm ci is stubbed.
  • git diff touches exactly scripts/build-deb.sh, test/build-deb.test.js and one changelog.d/*.md.
  • npm test passes and ci / test is green on the PR head.

The merge releases the claim; no builder owes a draft. Triage owes completion in a follow-up comment that names the owner and wake condition.

<!-- issueflow:post-merge-transition-pr-68 --> The Refs-linked PR merged with these acceptance criteria still unchecked: - [ ] Replace L72 with the `u+rwX,go=rX` normalization and correct the L70-71 comment to match. - [ ] Add `test/build-deb.test.js` per the Spec: temp `ROOT`, stubbed `npm`, `umask 077`, assertions from `dpkg-deb -c`. - [ ] Add a `changelog.d/` fragment. - [ ] Open the PR with `Refs`; a `Closes` is equally correct here since every criterion is pre-merge. - [ ] Building under `umask 077` produces a `.deb` in which every directory under `./usr/` is `0755`, every regular file is `0644` except those that were executable, and `./usr/lib/stoke/src/cli.js` is `0755`. - [ ] The same build under `umask 022` produces byte-identical modes to the `umask 077` build — the point is that the umask no longer reaches the artifact. - [ ] `test/build-deb.test.js` fails when L72 is reverted to `chmod -R go-w`. State this in the PR body having actually tried it; a permissions test that passes against the unfixed script is not a test. - [ ] The test writes nothing outside its temp directory — in particular the repository's `dist/` is untouched by `npm test`. - [ ] No network access in the test; `npm ci` is stubbed. - [ ] `git diff` touches exactly `scripts/build-deb.sh`, `test/build-deb.test.js` and one `changelog.d/*.md`. - [ ] `npm test` passes and `ci / test` is green on the PR head. The merge releases the claim; no builder owes a draft. Triage owes completion in a follow-up comment that names the owner and wake condition.
forgejo-actions added
post-merge
and removed
claimed
labels 2026-09-04 07:26:22 +00:00
codex-bot-andresmgsl was unassigned by forgejo-actions 2026-09-04 07:26:23 +00:00
Author
Member

Completing this per TRIAGE.md's post-merge clause — "triage's completion queue, not a parked claim.
Tick verified criteria and close under the criterion's existing contract."

Answering the transition comment's list directly: all eleven are now ticked, none remain, and no
criterion here is post-merge
— the issue said so when it was minted ("a Closes is equally correct
here since every criterion is pre-merge"
), so there is no follow-up owner and no wake condition to
name. The full measurement is in the body under ## Completion; the short form:

  • Modes — two builds staged in temp roots from merged main (33d58389), umask 077 and
    umask 022, dpkg-deb -c on each: all ./usr/ directories 0755, all regular files 0644,
    cli.js alone 0755, and the two listings diff clean. ./usr/lib/stoke/src/ is now
    drwxr-xr-x where the Context transcript had drwx------ — the EACCES failure is gone.
    lintian under 077 emits zero non-standard-file-perm warnings, against three before.
  • Mutation proof re-run, not taken on the PR's word — L72 alone reverted to chmod -R go-w in a
    scratch tree, node --test test/build-deb.test.js1 fail, deepStrictEqual at
    test/build-deb.test.js:61, reporting the 0700/0600 modes.
  • Hermeticitynpm test at merged main 150/150 with the new subtest ok; afterwards no
    dist/ and a clean git status --porcelain; the stub shadows the only network command (L32
    npm ci) and no node_modules is produced.
  • Scope and CI — diff is exactly the three intended files; ci / test on 44bbeadf success,
    run 1228 read end to end.

Two notes for the record. The negative control this issue was minted with still holds and did not
need re-taking: the published 1.5.0 package was already correct, because release.yml builds as root
at umask 022. Nothing shipped was ever broken; what this fixes is that the payload's modes were a
property of the build machine rather than of the build — invisible in the one environment CI runs in.
And per the Provenance section, this close settles !21's finding 2 under triage's 2026-08-30 call
that !21's close was hygiene and not a verdict on its findings; that call is now spent for this finding.

Completing this per TRIAGE.md's `post-merge` clause — *"triage's completion queue, not a parked claim. Tick verified criteria and close under the criterion's existing contract."* Answering the transition comment's list directly: **all eleven are now ticked, none remain, and no criterion here is post-merge** — the issue said so when it was minted (*"a `Closes` is equally correct here since every criterion is pre-merge"*), so there is no follow-up owner and no wake condition to name. The full measurement is in the body under **## Completion**; the short form: - **Modes** — two builds staged in temp roots from merged `main` (`33d58389`), `umask 077` and `umask 022`, `dpkg-deb -c` on each: all `./usr/` directories `0755`, all regular files `0644`, `cli.js` alone `0755`, and the two listings `diff` clean. `./usr/lib/stoke/src/` is now `drwxr-xr-x` where the Context transcript had `drwx------` — the `EACCES` failure is gone. `lintian` under `077` emits zero `non-standard-file-perm` warnings, against three before. - **Mutation proof re-run, not taken on the PR's word** — L72 alone reverted to `chmod -R go-w` in a scratch tree, `node --test test/build-deb.test.js` → **1 fail**, `deepStrictEqual` at `test/build-deb.test.js:61`, reporting the `0700`/`0600` modes. - **Hermeticity** — `npm test` at merged `main` 150/150 with the new subtest `ok`; afterwards no `dist/` and a clean `git status --porcelain`; the stub shadows the only network command (L32 `npm ci`) and no `node_modules` is produced. - **Scope and CI** — diff is exactly the three intended files; `ci / test` on `44bbeadf` `success`, run 1228 read end to end. Two notes for the record. The **negative control this issue was minted with still holds** and did not need re-taking: the published `1.5.0` package was already correct, because `release.yml` builds as root at `umask 022`. Nothing shipped was ever broken; what this fixes is that the payload's modes were a property of the build machine rather than of the build — invisible in the one environment CI runs in. And per the Provenance section, this close settles **!21's finding 2** under triage's 2026-08-30 call that !21's close was hygiene and not a verdict on its findings; that call is now spent for this finding.
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/stoke#63
No description provided.