Conversation
…s, and UI wizard Add 12 stages of functionality including: - Stage 9/17: Enhanced 8-step wizard UI with SeverityBadge, DiffViewer, TreePreview, FindingsFilter components and deeper page integration - Stage 10: History preservation prerequisites and dry-run reporting - Stage 11: Full lifecycle CLI commands (add, archive, migrate-branch) with plan types - Stage 12: Extended analysis (environment, tooling, CI, publishing, repo risks) with risk classification - Stage 13: Path-filtered GitHub Actions workflow generation - Stage 14: Configure engine for Prettier/ESLint/TypeScript scaffolding - Stage 15: Dependency enforcement via overrides/resolutions - Stage 16: Cross-platform path normalization - Stage 18: Smart defaults with evidence-based suggestions and error shaping - Stage 19: Multi-language detection and scaffolding (Go, Rust, Python) - Stage 20: Performance utilities (pMap concurrency, disk space check, progress emitter) 674 unit tests passing across 49 test files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
||
| // Fetch | ||
| logger.info(`Fetching ${branch}...`); | ||
| await safeExecFile('git', ['fetch', remoteName, branch], { |
Check failure
Code scanning / CodeQL
Second order command injection High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 17 days ago
In general: to fix this issue, we must validate and constrain user-controlled values before they reach git. For branch, that means only permitting branch-like names (e.g., alphanumerics plus a small set of punctuation such as /, -, _, ., limiting length, and rejecting values that start with - or contain whitespace or globbing characters). Similarly, we should restrict subdir (coming from options.subdir or defaulting to plan.sourceRepo) to a safe relative path pattern and disallow .., absolute paths, or path separators that could escape the repo. sourceRepo and targetMonorepo appear to be local filesystem paths; these are used as cwd and remote URL for git remote add, so at minimum we should ensure they are strings and non-empty, but the second-order injection highlighted by CodeQL is primarily about the branch argument.
Best single fix without changing existing behavior: add explicit validation helpers in src/server/routes/migrate-branch.ts and apply them to branch and options.subdir before we ever call generateBranchPlan/applyBranchPlan. This keeps all logic at the HTTP boundary and avoids modifying the strategy logic. Concretely:
- In
src/server/routes/migrate-branch.ts, define:isValidBranchName(name: string): booleanusing a conservative regex (e.g.,/^[A-Za-z0-9][A-Za-z0-9._/-]{0,254}$/) and additional checks like “not starting with-” and no consecutive..to keep it simple and safe.isValidSubdir(subdir: string): booleanthat ensures it’s a relative directory name without.., without starting with/or\, and containing only safe characters likeA-Za-z0-9._/-.
- In the POST handler:
- After checking
branchis a string, callisValidBranchName(branch); if it fails, return HTTP 400 with a clear error. - If
options?.subdiris provided, check it is a string and passesisValidSubdir; otherwise return 400.
- After checking
- Then pass
branchandoptions.subdiras before. Because we are only rejecting obviously unsafe names and not transforming values, normal use (with typical git-style branch names) will continue to work.
No changes to imports are strictly required (we can implement these helpers inline). We do not need to alter src/strategies/migrate-branch.ts for this fix; validating at the route layer is sufficient to break the tainted flow.
| // Use wmic on Windows | ||
| const drive = path.parse(path.resolve(dirPath)).root; | ||
| const { stdout } = await execFileAsync('wmic', [ | ||
| 'logicaldisk', 'where', `DeviceID='${drive.replace('\\', '')}'`, |
Check failure
Code scanning / CodeQL
Incomplete string escaping or encoding High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 17 days ago
In general, when sanitizing strings by removing or escaping certain characters, use a global regular expression (/pattern/g) so that all occurrences are handled, not just the first. For backslash removal, this means using .replace(/\\/g, '') instead of .replace('\\', '').
For this specific code in src/utils/disk.ts, update the construction of the DeviceID filter on line 18 so that all backslashes are removed from drive. Change:
`DeviceID='${drive.replace('\\', '')}'`,to:
`DeviceID='${drive.replace(/\\/g, '')}'`,This preserves the intended functionality—turning "C:\\" into "C:"—while correctly handling any unexpected extra backslashes in drive. No new imports or auxiliary methods are needed; this is a localized change within the existing function.
| @@ -15,7 +15,7 @@ | ||
| // Use wmic on Windows | ||
| const drive = path.parse(path.resolve(dirPath)).root; | ||
| const { stdout } = await execFileAsync('wmic', [ | ||
| 'logicaldisk', 'where', `DeviceID='${drive.replace('\\', '')}'`, | ||
| 'logicaldisk', 'where', `DeviceID='${drive.replace(/\\/g, '')}'`, | ||
| 'get', 'FreeSpace', '/format:value', | ||
| ]); | ||
| const match = stdout.match(/FreeSpace=(\d+)/); |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ckers SEC-01: Sanitize Python injection in history-preserve commitPrefix SEC-02: Add path traversal prevention in apply command SEC-03: Add Bearer token auth to server API and WebSocket SEC-04: Allowlist install command executables in apply SEC-05: Replace shell exec() with execFile() in ui command SEC-06: Cap concurrent operations and event buffer in WsHub Publishing: rename to monotize, add LICENSE/SECURITY.md/CHANGELOG.md, add files field, author, repository metadata, semver and js-yaml deps. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
add,archive,migrate-branch) with typed plan artifacts (AddPlan, ArchivePlan, BranchPlan)Test plan
tsc --noEmit) passes cleanlynode bin/monorepo.js --helpshows all commandsnode bin/monorepo.js uiserves working wizard🤖 Generated with Claude Code