Skip to content

Register --only-uncommitted scans as partial scans - #186

Open
Ibrahimrahhal wants to merge 1 commit into
mainfrom
cursor/only-uncommitted-partial-scan-8688
Open

Ibrahimrahhal wants to merge 1 commit into
mainfrom
cursor/only-uncommitted-partial-scan-8688

Conversation

@Ibrahimrahhal

Copy link
Copy Markdown
Member

Why

corgea scan --only-uncommitted uploaded an archive of only the changed files, with no partial-scan marker. The server registered that as the branch's latest full scan, so the project page and GET /issues?project=&branch= showed only those files' issues.

Change

  • --only-uncommitted now packs the whole project, the same as a normal scan, and sends partial_scan=true plus files_to_scan (a JSON array of zip entry names). This is how pull request scans are registered.
  • The uncommitted selection (git:staged,git:modified,git:untracked) is resolved separately and matched against the archive's entry names (ArchiveContents.entry_names). Files that packaging leaves out, such as vendored or generated files or files outside the scanned directory, are listed as skipped instead of being sent. Sending them would fail the upload on the server. Force-included files are added to the list.
  • Partial scans upload with dirty=true, build no file manifest and skip incremental planning, so they can never be used as a commit baseline.
  • With --include-image and no scannable changes, the scan is still partial, with files_to_scan=[].
  • Updated the --only-uncommitted and --disable-incremental help text.

Dependencies

Requires Corgea/doghouse#2348, which accepts a JSON files_to_scan and registers CLI partial scans. Deploy that before releasing this change.

Tests

  • New unit test for partial_scan_files.
  • New integration test: the upload contains the committed files, partial_scan=true, files_to_scan=["edited.py"], dirty=true, and no file_manifest.
  • The existing include-image test now also checks for files_to_scan=[].
  • ./harness check: clippy, format, and 953 tests all pass.
Open in Web Open in Cursor 

Pack the whole project and send the uncommitted files as files_to_scan with
partial_scan=true, the way pull request scans are registered, instead of an
archive of only those files that the server took for the branch's full state.
@Ibrahimrahhal
Ibrahimrahhal marked this pull request as ready for review October 7, 2026 08:03
Comment thread src/scanners/blast.rs
Some("git:staged,git:modified,git:untracked")
// Only --target narrows the archive. --only-uncommitted packs the whole
// project and names its files in the upload, the way a pull request scan is
// registered: an archive of just those files reads to the server as the

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high: --target can incorrectly narrow an --only-uncommitted scan

The previous logic gave --only-uncommitted precedence over target. The new code always assigns target_str from --target while independently resolving all uncommitted files. Packaging is therefore target-limited, and partial_scan_files later intersects the uncommitted set with that archive. An uncommitted file outside --target is skipped or can cause the command to report no scannable changes, despite the help text promising that --only-uncommitted uploads the whole project. Either make these options explicitly conflict or preserve --only-uncommitted precedence.

Proof or reproduction:

Given committed main.py and modified edited.py:

corgea scan --only-uncommitted --target main.py

The archive contains only main.py, while selected contains edited.py. Since archived.contains("edited.py") is false, partial_scan_files places it in skipped and returns an empty files list, causing the scan to exit even though edited.py is a valid uncommitted source file.

@corgea-security corgea-security left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review risk: 3/5.

The new partial-scan flow is generally coherent, but combining --only-uncommitted with --target can silently narrow the archive and omit uncommitted files, contradicting the documented behavior.

Critical or high-priority changes must be addressed.

Automatic approval was not submitted: automated review found critical or high-priority findings.

@corgea-security corgea-security added the dennis-reviewed Dennis completed an automated review label Oct 7, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--only-uncommitted drops git changes the old packer scanned. files_to_scan is intersected with the standard-filter project walk, so hidden paths and tracked files that match .gitignore never enter the archive and are then skipped. A workflow-only edit exits 1; a mixed commit succeeds without scanning that file.

Open in Web View Automation 

Sent by Cursor Automation: pr-flow

Comment thread src/scanners/blast.rs
Comment on lines +633 to +637
let (files, skipped) = partial_scan_files(
&selected,
&roots,
&force_included,
&archive_contents.entry_names,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

entry_names comes from create_zip_from_target with target == None, which walks with WalkBuilder::standard_filters(true) (src/utils/generic.rs:212). That walk skips hidden paths and .gitignore matches, including files that are still tracked. git:staged / git:modified still return those paths (src/targets.rs:275-280), archived.contains fails, and partial_scan_files reports them skipped.

Reproduced with the same filters: after committing and editing .github/workflows/ci.yml, a force-added ignored.py, and src/app.py, git status --porcelain lists all three. A default rg walk (same ignore crate defaults) lists only src/app.py. The new test only adds an untracked root edited.py, so it stays green.

The previous --only-uncommitted path passed git:staged,git:modified,git:untracked as the zip target, which packs those paths directly and only then applies DEFAULT_EXCLUDE_GLOBS. Both the workflow file and ignored.py were uploaded.

Impact: the pre-commit hook (setup_hooks.rs) runs corgea scan blast --only-uncommitted --fail-on LO. A commit that only changes .github/workflows/ci.yml now exits 1 with "no scannable uncommitted changes". A commit that also touches a normal source file succeeds, warns that the workflow is not source code, and omits it from files_to_scan, so --scan-type secrets never sees a secret added there.

Do not fix this by naming files that are absent from the zip; the server rejects that and fails the upload. After the walker builds files_to_zip, add resolved uncommitted files that exist on disk and are not matched by DEFAULT_EXCLUDE_GLOBS or --exclude. force_include is the wrong hook: it also bypasses those globs and would start scanning tests/**, *.css, and *.env. Cover it by extending scan_only_uncommitted_uploads_the_project_and_names_the_changed_files with a modified .github/workflows/ci.yml and a tracked gitignored file, and assert both names are in the zip and in files_to_scan.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dennis-reviewed Dennis completed an automated review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants