fix: harden scaffold — execFileSync, re-run guard, slug validation#38
Merged
Conversation
…loses #23, #24) #23 (shell injection): - Replace the interpolated `execSync("gh label create ...")` with `execFileSync("gh", [...])`, so label fields containing quotes/backticks/$/; can never break or inject into a shell command. - Surface the underlying gh error (not installed / not authenticated / wrong repo) at least once instead of swallowing it in an empty catch. #24 (robustness): - Re-run guard: abort with a clear message if `.construct` already exists (already scaffolded, or a previous run failed partway). - Harden slugify (collapse non-alphanumeric runs to single hyphens, trim leading/trailing) and fall back to "my-project" when a name slugifies to nothing — never write an invalid package.json name. - `delete pkg.scripts.scaffold` instead of relying on JSON.stringify dropping an `undefined` value. - Surface a clear partial-state error (with a git reset hint) if a file mutation throws mid-run, rather than a raw stack trace. True rollback isn't feasible once files are written/deleted. Verified by replicating the scaffold flow: normal run scaffolds + self-cleans (scaffolded tsc/vitest/biome pass); the re-run guard aborts on a pre-existing .construct; "!!!" falls back to my-project; and a failing gh surfaces its error. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
biome's lint/performance/noDelete rule rejected `delete pkg.scripts.scaffold`, failing CI. Rebuild `pkg.scripts` without the `scaffold` key via Object.fromEntries/filter instead — still a clean key removal (not the incidental JSON.stringify undefined-drop the issue called out), and lint-clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #23 and #24 (both rewrite
scripts/scaffold.mjs, so combined into one PR).#23 — shell-injection / error swallowing
execSync(\gh label create "..."`)withexecFileSync("gh", [...argv]), so label fields containing quotes, backticks,$,;`, etc. can never break or inject into a shell command.gherror (not installed / not authenticated / wrong repo) is now surfaced once instead of being swallowed by an emptycatch {}.#24 — robustness
.constructalready exists (already scaffolded, or a prior run failed partway).slugifynow collapses non-alphanumeric runs to single hyphens and trims leading/trailing ones; falls back tomy-projectwhen a name slugifies to nothing, so we never write an invalidpackage.jsonname.delete pkg.scripts.scaffoldinstead of relying onJSON.stringifydroppingundefined.git checkout . && git clean -fdrecovery hint instead of a raw stack trace. (True rollback isn't feasible once files are written/deleted; this is the pragmatic interpretation.).envconsistency" was already handled in [Task]: Fix documentation & setup-instruction accuracy #26.Verification (replicated scaffold flow)
tsc/vitest(10/10) /biomepass..construct."!!!"falls back to package namemy-project.gh(no auth/remote) surfaces its error and continues.🤖 Generated with Claude Code