fix(catalog): project installability into skill index - #311
Conversation
| async function readSkillJson(skillJsonPath, label) { | ||
| let source; | ||
| try { | ||
| source = await readFile(skillJsonPath, "utf8"); | ||
| } catch (error) { |
There was a problem hiding this comment.
Unvalidated CLI paths enable file read
--release-skill-json / --repository-skill-json flow from argv into readSkillJson(), which passes them straight to await readFile(skillJsonPath, "utf8"), so the CLI can read any local JSON file the invoker names — should we confine these paths to the repo root or an allow-list?
Want Baz to fix this for you? Activate Fixer
Other fix methods
Prompt for AI Agents
Before applying, verify this suggestion against the current code. In
scripts/ci/project_skill_catalog_installability.mjs around lines 20-36 in
`readSkillJson()` (and around lines 119-158 in `readOptionValue()`/`parseArgs()`),
don’t accept the CLI-provided path verbatim and pass it to `readFile`. Refactor by
adding a dedicated path-sanitization helper that resolves the given path against an
allowed base directory (e.g., the repo root), rejects absolute paths and any traversal
(like `..`), restricts to `.json` files, and verifies the resolved (real) path stays
within the base directory to prevent symlink escape. Then call `readSkillJson()` only
with the validated/constrained path and update the thrown errors to clearly indicate
invalid/unallowed paths.
| SKILL_DATA=$(jq -c \ | ||
| --arg tag "$TAG" \ | ||
| --argjson installable "$EFFECTIVE_INSTALLABLE" ' | ||
| . as $skill | |
There was a problem hiding this comment.
Duplicated catalog projection
The jq program that builds each catalog entry is duplicated verbatim in scripts/populate-local-skills.sh and .github/workflows/deploy-pages.yml, so schema or defaulting changes have to be updated in two places and the Pages/local catalog paths can drift — should we move the JSON projection into a shared helper, like a small Node script both call?
Want Baz to fix this for you? Activate Fixer
User description
Summary
installableboolean into the Pages and local skill indexestruefor an absent field on an existing recordskill.jsonbytes unchangedScope
This is the projection-only PR from the multi-harness design. It does not yet make the website or
clawsec-suiteconsume the projected denial; those remain separate follow-up PRs.Changed paths:
.github/workflows/deploy-pages.ymlscripts/populate-local-skills.shscripts/ci/project_skill_catalog_installability.mjsscripts/test-skill-catalog-installability-projection.mjsThis PR is stacked on
davida-ps/nanoclaw-v2-truthfulness, which contains the shared installability contract and NanoClaw tombstone used by the projection.Security behavior
falseRemote validation
All executable validation ran only on
davida@20.14.133.241in preserved quarantine:/tmp/clawsec-catalog-projection.hAf0TD/sourceThe remote checkout was pinned to base
ffe94d3b1e5f596d8dc1ce8c72ce49ebdca70775. Only the four reviewed files were transferred. Their remote SHA-256 values matched the reviewed local files.npm ci— 422 packages, 0 vulnerabilitiesnode scripts/test-skill-catalog-installability-projection.mjs— passedscripts/test-skill-*.mjs— passedbash scripts/populate-local-skills.sh— passed with 15 public skillsclawsec-nanoclaw=false, field-absentclawsec-suite=trueskill.jsonhashes — byte-identicalbash -n scripts/populate-local-skills.sh— passednpx eslint . --ext .ts,.tsx,.js,.jsx,.mjs --max-warnings 0— passednpx tsc --noEmit— passednpm run build— passed; 115 wiki exports generatedThe remote host's system
zipis incompatible with the tag-release simulation, so the full-suite rerun used the previously reviewed narrowzip -qr <archive> .compatibility wrapper with SHA-256472456191504d886c5871da3e900797512ab9266b8426d736c6a0f48248046b0.Release impact
No tags, releases, publications, or store writes are performed by this PR.
Generated description
Below is a concise technical summary of the changes proposed in this PR:
Project effective skill installability into the Pages deploy flow and the local catalog population flow by wiring both through
project_skill_catalog_installability.mjs. Keep releaseskill.jsonbytes immutable whiledeploy-pagesandpopulate-local-skills.shbind repository metadata to the tag/directory skill identity and fail closed on invalid lifecycle state.installableflag from release and repository metadata, and publish it into the Pages and local skill indexes without mutating copiedskill.jsonartifacts.Modified files (3)
Latest Contributors(2)
Modified files (1)
Latest Contributors(1)