Unify planning pipeline + harden semver/lockfile analyzers#11
Unify planning pipeline + harden semver/lockfile analyzers#11
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>
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>
|
|
||
| // 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 25 days ago
At a high level, the fix is to validate and constrain the user-provided branch (and related path-like values) before they are used in git commands or as filesystem subpaths. We should accept only syntactically valid git ref names, reject anything containing dangerous characters or starting with - (which could be interpreted as an option), and ensure there is no path traversal (..) or embedded whitespace. This keeps the application’s behavior the same for legitimate inputs while blocking malicious ones.
The best single approach here, without changing overall functionality, is:
-
Introduce small helper functions in
src/strategies/migrate-branch.tsto validate:branchas a git ref name (no leading-, no whitespace, no control characters, no.., and excluding characters disallowed by git in ref names such as~,^,:,?,*,[,\, and..segments).subdir(which ultimately comes fromoptions.subdirorplan.sourceRepo) as a safe relative directory or absolute path without..segments when used as a--prefixor--directoryargument.
-
Call these validators early in
generateBranchPlan(forbranch) so that theBranchPlanitself is always safe, and again inapplyBranchPlan(for the effectivesubdirvalue, which is not part of the plan but is derived from request options). -
If validation fails, throw an error with a clear message; this will be caught by the existing
try/catchin the route and reported to the client as an error, preserving the overall error-handling flow.
Concretely:
- In
src/strategies/migrate-branch.ts, abovecheckBranchMigratePrerequisites, add two helper functionsvalidateBranchName(branch: string): voidandvalidateSubdir(subdir: string): voidthat perform the above checks and throw anErroron invalid input. - In
generateBranchPlan, immediately after receiving thebranchparameter (around lines 105–107), callvalidateBranchName(branch);. - In
applyBranchPlan, before dispatching toapplySubtreeImport/applyPatchReplay, callvalidateSubdir(subdir);. - Optionally, in the same file, we can reuse
validateBranchNamefor any other git-branch uses (branchMigrateDryRun), but the critical path highlighted by CodeQL isgenerateBranchPlan→applyBranchPlan→ git commands.
No external dependencies are required; we can implement the validation with simple regexes and string checks.
| // 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 25 days ago
In general, to fix this kind of issue you should either use a regular expression with the global (g) flag or use a utility that clearly operates on all occurrences (for example, split/join). This ensures that every instance of the character you intend to escape or remove is handled, not just the first one.
For this specific case, the safest and clearest fix is to remove all backslashes from drive before embedding it in the wmic query. A minimal change that preserves existing functionality is to replace drive.replace('\\', '') with a global replacement, e.g. drive.replace(/\\/g, ''). This removes all \ characters and matches the apparent intent of producing a device ID like C:.
Only one line in src/utils/disk.ts needs to change: line 18, where drive.replace('\\', '') appears. No new imports or helper methods are required.
| @@ -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+)/); |
| function extractRepoName(input: string, type: RepoSourceType): string { | ||
| if (type === 'local') { | ||
| // Handle POSIX, Windows drive, and UNC-style local paths. | ||
| const withoutTrailingSlash = input.replace(/[\\/]+$/, ''); |
Check failure
Code scanning / CodeQL
Polynomial regular expression used on uncontrolled data High
Summary
buildApplyPlancore moduleplanand serverrunPlanthrough the shared buildermergethrough plan+apply to eliminate duplicated pipeline logicValidation
pnpm buildpnpm exec vitest run tests/e2e/cli.test.ts tests/integration/plan-apply.test.ts tests/integration/prepare-plan-apply.test.ts tests/integration/verify-command.test.tspnpm exec vitest run tests/unit/analyzers/lockfile.test.ts tests/unit/analyzers/peers.test.ts tests/unit/analyzers/dependencies.edge-cases.test.ts tests/analyzers/dependencies.test.ts tests/unit/commands/verify-checks.test.ts tests/integration/verify-command.test.tscd ui && pnpm testpnpm run build:ui