Repository navigation
Tracking: scope project-mode cache crawls to what the project resolves #595
Description
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: E05.
Kind: tracking. Source: review §3 #3 and Part 6.6; register E05 (a step toward E36, one Inventory).
Problem
In local (project) mode, five crawlers return the whole machine cache as soon as the project has a marker file. Nothing narrows it to what the project resolves:
| Crawler | Marker gate | Root returned |
|---|---|---|
CargoCrawler::get_crate_source_paths |
Cargo.toml / Cargo.lock |
vendor/, else every $CARGO_HOME/registry/src/* |
GoCrawler::get_module_cache_paths |
go.mod / go.sum |
GOMODCACHE |
MavenCrawler::get_maven_repo_paths |
pom.xml, build.gradle*, settings.gradle* |
~/.m2/repository |
NuGetCrawler::get_nuget_package_paths |
any .csproj/.fsproj/.vbproj/.sln/.slnx, packages.config, nuget.config |
packages/, ~/.nuget/packages, every packageFolders key |
DenoCrawler::get_jsr_cache_paths |
deno.json(c) / deno.lock |
$DENO_DIR/npm/jsr.io |
scan feeds this crawl (crawl_every_ecosystem) to the patch API and to agent-mode apply and VEX. For Maven and NuGet the crawl is the only discovery.
Symptoms
- Maven hosted scan pins, and VEX attests, artifacts the project doesn't depend on (the crawler lists all of
~/.m2) #265: Maven hosted scan pins, and VEX attests, artifacts the project doesn't depend on (the crawler lists all of~/.m2). - Project-mode NuGet agent scan patches, and VEX attests, packages the project doesn't depend on (the crawler lists the whole ~/.nuget/packages) #427: project-mode NuGet agent scan patches, and VEX attests, packages the project doesn't depend on.
- Related, same cause (the crawl picks the machine copy, not the one the build reads): Agent-mode apply in a Gradle-only project patches the ~/.m2 copy Gradle never reads, reports success, and VEX attests not_affected while the build uses the unpatched ~/.gradle jar #551 (Gradle patches
~/.m2), Agent-mode NuGet apply patches ~/.nuget/packages instead of the project's configured globalPackagesFolder / RestorePackagesPath, reports success, and VEX attests not_affected #397 and Agent-mode NuGet apply ignores nuget.config repositoryPath for packages.config projects and patches ~/.nuget/packages instead, reporting success #398 (NuGetglobalPackagesFolder/repositoryPath), Agent-mode cargo apply patches only the first of several registry/src index dirs (cargo 1.84 vs 1.85+ hashes), so one cargo keeps building the unpatched crate while apply and VEX report success #339 (cargo patches only the firstregistry/srcindex dir).
Impact
These are wrong answers from a security tool: agent mode patches, and VEX attests, packages the project never uses, and scan sends every cached coordinate on the machine to the API. Scan cost grows with the machine cache, not with the project.
Target design
In project mode, crawlers become locators. The candidate set comes from the project's own resolution data, and the cache is consulted only to find the bytes for a coordinate:
fn project_coordinates(cwd) -> Option<Vec<Coordinate>>per ecosystem, built on the existing readers:Cargo.lock(formats::cargo),go.sum/go.mod(go_mod_edit/go_sum_edit),packages.lock.json/obj/project.assets.jsonlibraries, thedeno.lockjsrsection, and Maven/Gradle lockfiles or the reactor's resolved POM set (vendor::jvm).crawl_allin project mode becomesfind_by_purls(cache, project_coordinates). Enumerating the whole cache stays, for--global/--global-prefixonly.- When
project_coordinatesreturnsNone(no lock or resolution file), keep today's enumeration but emit an explicit warning code (for examplecrawl_unscoped_cache), so lockless projects keep working and the result is labelled. Existing warning codes don't change.
Checklist (one PR each, in order)
- NuGet: scope to
obj/project.assets.jsonlibraries(fallbackpackages.lock.json). Child: Project-mode NuGet agent scan patches, and VEX attests, packages the project doesn't depend on (the crawler lists the whole ~/.nuget/packages) #427. - Maven/Gradle: scope to the reactor's resolved coordinates. Child: Maven hosted scan pins, and VEX attests, artifacts the project doesn't depend on (the crawler lists all of
~/.m2) #265. - Cargo: scope to
Cargo.lock[[package]]entries with a registry source. - Go: scope to
go.summodule lines (the/go.mod-only lines don't count). - Deno: scope to the
deno.lockjsrentries. - Shared: the
crawl_unscoped_cachewarning, documented inCLI_CONTRACT.md.
Each child deletes its whole-cache path from project mode and adds a test with an unrelated package in the fake cache that must not appear in crawl_all.
Acceptance criteria
- In project mode with a lock or resolution file, no crawler returns a package the project doesn't resolve.
-
--globaloutput is unchanged. - The crawler oracle and equivalence suites, which encode today's whole-cache output, are updated deliberately rather than silenced.
Dependencies
Part of E36 (one Inventory). The NuGet child benefits from the shared packages.lock.json walker in #593 but doesn't need it. The FIFO fix #592 touches the same crawlers and should land first.
Activity
audit-ecosystems: E05/E06/E11 filed (#592, #594, #595), new finding E…
mikolalysenko commentedon Oct 2, 2026
[agent] Triage: priority:p3 (cross-cutting tracking issue). Children are tracked individually (#427, #265); #592 should land first, as noted.
Generated by Claude Code
Scope project-mode Go crawl to go.sum modules