Skip to content

v2.8.6 - the apply check now refuses a name ending in a dot or a space

Choose a tag to compare

@github-actions github-actions released this 18 Oct 09:20
· 55 commits to main since this release
v2.8.6
d572f4c

The apply check now refuses a name ending in a dot or a space.

Security

  • The final-consent apply check refuses a target name that ends in a dot or a space. Windows strips a trailing dot or space from a path component, so foo. and foo name one file, and a target spelled with such an ending could be judged under one spelling and written under the other. skills/coalboard/scripts/apply-target.mjs now refuses, on every platform, a target with a segment below the project root that ends in a dot or a space, with the new reason name (REFUSE <target> name -); the digest and the report name it as not applicable, like any other refused target, so "apply all" never covers it. The segments of the project root itself are not judged, and .. is not treated as a name. That the agent runs the checker is still an instruction it follows, a mitigation and not a guarantee. — test: scripts/lib/apply-target.test.mjs
  • scripts/configure.mjs no longer makes a folder, or writes a config, through a link or junction. Before, a junction or symlink planted at .claude or .claude/coal in a cloned project made the tool create the config folder at the link's target, outside the project, and write the config there. It now checks the config folder's path first, one component at a time and before it makes any folder: a link or junction on the path is refused wherever it points (even into the project), nothing is made beyond the last checked component, and the tool prints the refusal with a fix (make the path a real folder inside the project, or remove the link) and exits 1. It also refuses to write when the config file itself is a symlink, refuses a legacy config that is a link at the place it is read from, and refuses a link or junction at the <config>.bak name when a backup of a malformed config is due (a link there does not block a write over a valid config); a refusal leaves no .bak behind. A linked ~/.claude folder still works for --global; a symlink at the global config file itself is refused. The project root is derived from where the config was found, so a config found above the current folder is judged against its own project. Not shipped in the plugin. — test: scripts/configure.test.mjs, scripts/lib/repo-fs.test.mjs
  • scripts/configure.mjs writes the config through a temp file and a rename; not shipped in the plugin. The config is written to a temp file opened exclusively in the config's own folder, then renamed over the target (writeConfigAtomic); a failure leaves the old file untouched, removes the temp file and reports the error, and never falls back to an in-place write. So a link planted at the config file's name after the checks is replaced, not written through, and a process crash leaves the old file or the new one, never a torn one (a power loss is not covered: there is no fsync). It does not close the folder-swap window: a checked folder swapped for a junction before the temp file is made still lands the temp file and the rename outside the project. — test: scripts/configure.test.mjs
  • scripts/configure.mjs keeps the old config file's permission bits when it rewrites the config; not shipped in the plugin. The temp-then-rename write above would otherwise have replaced the file with one made under the default mode, so a config a user had set to 0600 came back wider. The temp file is now opened with the old file's mode and set to it explicitly (the umask would otherwise narrow it); a first write still takes the default mode. Nothing is claimed here about the .bak copy's mode: it was not measured on POSIX. — test: scripts/configure.test.mjs

Changed

  • Named residual: configure.mjs's project-config write has a check-to-write window. The tool checks the config folder's path (mkdirRepoParents) and the config file (refuseLinkedTarget) before it makes the missing folders, then writes through a temp file and a rename (writeConfigAtomic). A hostile local process that swaps a checked folder for a junction to outside before the temp file is made can still land the temp file and the rename outside the project. The per-component walk narrows the window; it does not close it. A link planted ahead of time is refused before anything is made. SECURITY.md names it.
  • The canon files are re-copied by blob from the .github canon at bea2b3d; not shipped in the plugin. scripts/lib/wave-run.mjs b60827c6, scripts/lib/wave-run.test.mjs bccbaa58, scripts/release-notes.test.mjs f9dde432, scripts/lib/git-env-census.vectors.mjs 6dc3ad82 and scripts/verify-release-shape.test.mjs 7c2b35c4. NOTICE now counts as a doc path in the CI and CodeQL doc-only filters and is ignored by the Scorecard trigger, as in the canon. NOTICE itself takes the canon template's wording.
  • The front-door links workflow is re-copied by blob from the canon at .github 7794678; not shipped in the plugin. .github/workflows/front-door-links.yml is now f0cc9ec0 (was 7c582bd7): its job is named front-door-links instead of check, so it can no longer meet the required check context that belongs to link-check.yml. — test: scripts/front-door-links.test.mjs