input validation: unchecked values reach destructive and authoritative paths #117
Labels
No labels
already-shipped
bug
documentation
duplicate
enhancement
external-review
good first issue
help wanted
in progress
invalid
needs-decision
proposal
question
security
wontfix
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: crenshawdev/cadence-archived#117
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Three places take input that was never validated and act on it destructively or authoritatively.
1. A valueless flag becomes the integer 1
parseArgs(planning.mjs:2889-2890) gives a flag with nothing after it the booleantrue, andNumber(true) === 1. Three sites use bareNumber(opts.x):planning.mjs:483(phase-done)planning.mjs:673(uat record)planning.mjs:2471(renumber)lib/require-int.mjs's own header names this exact hazard - "or, worse, to a wrong-but-valid int likeNumber(true)===1" - andrequire-int.test.mjs:23tests it.--phase,--total,--attempt,--tokens,--read,--step,--roleand--criterionall route through it. These three skip it.All three reproduced:
The trigger is ordinary:
--n "$PHASE"unquoted with$PHASEunset drops the token.--itemis worst becauseuat record's guard order putsNumber()BEFORE theunknown-itemcheck, so the wrong item is found rather than refused.Fix:
requirePhaseArgat:483and:2471,requireIntat:673, plus the valueless-form test none of the three has.2. criteria-coverage exempts a phase whose CONTEXT.md is unreadable
planning.mjs:118read()collapses ENOENT with EACCES, EISDIR and EIO.:1247then treats null as "absent CONTEXT is nothing to prove (D-10)". D-10 was written for ABSENT.Two uncovered breaks become a clean pass.
self-verify.mjs:493-507guards this exact class deliberately and says why;planning.mjsnever adopted it.Fix: discriminate ENOENT from every other errno, and report a non-ENOENT failure as a break rather than an exemption.
3. Path traversal through milestone-prune --label
planning.mjs:2812trims the label and nothing else;:2847buildsjoin(dir, '_archive-' + label);:2854-2855mkdir and rename into it.Directories created and phase directories relocated outside the tree. Per
workflows/milestone.md:87the label is "the version on a release, else the milestone name from PROJECT.md" - an LLM-authored planning artifact.Fix: validate against
/^[A-Za-z0-9][A-Za-z0-9._-]*$/, the shapepublish-decision.mjs:28already uses for branch and remote names, and refuse otherwise.Fixed in v3.2.0 (PR #124). VAL-01, phase 2. A valueless flag can no longer become the integer 1 at phase-done, uat record or renumber, each with the valueless-form test it lacked. An unreadable CONTEXT.md is reported as a break rather than granted the exemption written for an absent one, and a --label that escapes the tree is refused before any mkdir or rename.
Verified through the phase UAT walk. The milestone audit traced 12/12 requirements with 0 broken and 36/36 acceptance criteria covered.