CodeVetter · Repo Unpack · Risk map
chromaui/chromatic-cli
These are source observations and explicitly labeled hypotheses, not confirmed vulnerabilities. Sensitive boundaries include credential exchange, shell command construction, repository mutation, filesystem traversal, and diagnostic uploads. Compatibility hotspots include shared Context access and persistent hash contracts across CLI versions. Mock-based tests provide useful behavioral specifications but do not validate these boundaries against a live service or real user workspace in this investigation.
- execGit uses shell:true while Git helpers interpolate revisions, branch references, and paths into command strings; findMergeBase and checkout therefore require careful input/escaping review at callers. No exploit was tested.
- Patch restoration executes git reset --hard before and after dependency installation; preparation checks a clean workspace, but isUpToDate returns true on remote-update or revision lookup errors, and restoration failures are logged without masking the original pipeline error.
- Interactive checkPackageJson builds a persisted npm script from originalArgv.join(' '); if a project token was supplied on argv, the resulting package.json script can retain it. This path is gated by interactive mode and confirmation.
- TurboSnap enables metadata upload by default once a build Storybook URL exists; the upload list includes logs, diagnostics, main/preview configuration, trimmed stats, and the manifest. Diagnostics redact three named token fields, but that redaction is not applied by uploadMetadataFiles to every listed file.
- readMainConfig first evaluates the project's main configuration through require before falling back to AST parsing; metadata discovery is consequently a code-execution boundary, even before the explicit Storybook build command.
- Artifact enumeration uses statSync, which follows symlinks, without the ancestor-cycle tracking present in the v2 ProjectFiles tree walker; user-selected output/config/static paths can consequently involve filesystem locations beyond a repository-local artifact tree.
- Hypothesis: a build that never receives completion may wait indefinitely during snapshot monitoring. The inspected GraphQL completion loop has delay-and-recurse behavior without a local deadline or abort check, and the notify function accepts no AbortSignal; this was not reproduced. (inferred)
- Upload and TurboSnap preparation still thread the live Context through nominal task seams, and share stubs ctx.git with empty values; meanwhile v2 hash recipes persist across backend baselines. These are concrete coupling and compatibility hotspots for seemingly local refactors.