Skip to content

fix(scanner): resolve four defects found by post-merge audits - #159

Merged
JordanCoin merged 4 commits into
mainfrom
claude/codemap-prs-review-merge-nwifof
Aug 27, 2026
Merged

fix(scanner): resolve four defects found by post-merge audits#159
JordanCoin merged 4 commits into
mainfrom
claude/codemap-prs-review-merge-nwifof

Conversation

@JordanCoin

Copy link
Copy Markdown
Owner

What does this PR do?

Fixes four verified defects found by adversarial post-merge audits of the #123/#124/#127/#141 batch. Each fix landed with a regression test first proven to fail on unmodified main.

  1. Pass the absolute root into the deps scan (main.go, scanner/cargofallback.go). With a relative root — codemap --deps ., the documented invocation — a degraded ast-grep scan silently dropped the entire Cargo recovery (filepath.Rel(".", <abs manifest>) errors reject every package), mislabeled cargo-metadata authoritative, and ran cargo metadata twice. Relative and absolute roots now produce byte-identical output with honest fallback provenance and a single cargo run.
  2. Scan the same file universe in the Go fallback as the primary (scanner/cargofallback.go). The fallback fed itself from ScanFiles, which skips neither dot-directories nor nested git repos, so with ast-grep unavailable it reported phantom importers and flipped hub flags (160→312 files on this repo). The fallback now applies the primary's hidden-dir and findNestedGitRepos exclusions. Relates to scanner: nested git worktrees inside the repo are scanned as project files (5.5x file-count inflation) #131 (this covers the fallback half; the primary-walker aspect remains open).
  3. Don't resolve self/super use-paths inside inline modules (scanner/sg-rules/rust.yml, scanner/astgrep.go, scanner/rustgraph.go). #[cfg(test)] mod tests { use super::{a, b}; } resolved super against the file instead of the inline module, emitting false edges on name collisions (a file's own fn config vs sibling config.rs). The rule now splits into outside/inside-mod_item variants; self/super-rooted paths inside inline modules resolve to nothing (crate-rooted paths still resolve). The combined rule set was validated against both ast-grep 0.45.1 and the bundled 0.42.1, and the new rule ID is wired through all three dispatch lists.
  4. Stop the rust-use raw-imports leak and standardize the byExact uniqueness idiom (scanner/astgrep.go, scanner/rustbuildscript.go, scanner/rustgraph.go). Raw brace text like crate::{a::one, b::two} no longer ships in the versioned imports array, and resolveRustBuildScriptInput / resolveRustAskamaTemplate now use the exact-count idiom from resolveRustInclude, so an extension-sibling (data.json.gz, template.html.orig) no longer blocks resolution of the real target. Relates to buildFileIndex: byExact double-indexing causes both phantom keys and unresolvable extension-less files #130 (the extensionless double-indexing itself stays with that issue).

The fifth audit finding — cmd.exe quote-stripping breaking Windows shim scans for paths with spaces — is deliberately excluded: it needs Windows validation and its own PR.

Type of change

  • Bug fix
  • New feature
  • New language support
  • Documentation
  • Other (describe below)

Checklist

  • I've tested this locally with go build && ./codemap .
  • I've read CONTRIBUTING.md (for new language support)
  • I've updated documentation if needed

Additional notes

Each commit is one fix with its regression tests; CLI reproductions were verified before/after with built binaries (cargo-call-counting wrapper for fix 1, ast-grep hidden from PATH for fixes 1–2, real ast-grep end-to-end for fix 3). go vet ./... clean; full go test ./... green apart from the three known root-environment permission tests.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PEUvjGsJemDFSV8nbxvxBo


Generated by Claude Code

claude added 4 commits August 27, 2026 16:16
runDepsMode passed the raw CLI root (e.g. ".") into the deps scan
instead of absRoot. With a relative root and a degraded/absent
ast-grep, buildCargoFallbackOutcome resolved each package's absolute
manifest_path against that relative root, filepath.Rel errored, and
every cargo-metadata package was silently dropped -- losing the
recovered Rust edges and causing cargo metadata to run a second,
redundant time during graph build. Pass absRoot at the call site, and
absolutize root defensively at the top of
scanForGraphOutcomeWithFilters.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PEUvjGsJemDFSV8nbxvxBo
scanForGraphOutcomeWithFilters fed the Go fallback from ScanFiles,
which -- unlike the ast-grep primary -- does not skip dot-prefixed
directories or nested git repos (findNestedGitRepos exists precisely
for that). With ast-grep unavailable, hidden dirs and nested repos
contributed phantom Go analyses, inflating importers/hub flags beyond
what the primary would report. buildGoFallbackOutcome now drops files
under a dot-prefixed directory component or a nested-repo subtree
before parsing them.

Relates to #131

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PEUvjGsJemDFSV8nbxvxBo
`use super::{a, b};` inside an inline module (e.g. `#[cfg(test)] mod
tests { ... }`) is relative to that module, not the file, but
expansion treated it as file-relative and could resolve `super::x` to
an unrelated sibling file that happens to share x's name. Split
rust-use-imports into an outside-mod_item rule (unchanged behavior)
and an inside-mod_item variant whose handling drops self/super-rooted
paths instead of resolving them -- a missed edge beats a wrong one.
crate::-rooted paths mean the same thing everywhere and still resolve
inside inline modules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PEUvjGsJemDFSV8nbxvxBo
(a) The imports-append exclusion list excluded askama, cargo-rerun,
and embedded-file kinds but not rust-use-imports, so raw brace-tree
text (e.g. crate::{a::one, b::two}) shipped verbatim in the versioned
imports array and fed --diff's basename matching as noise. Rust graph
edges come from References, which are unaffected.

(b) resolveRustBuildScriptInput and resolveRustAskamaTemplate used the
naive `len(idx.byExact[target]) != 1` shape, which drops a legitimate
target whenever a sibling shares its extension-stripped key (e.g.
data.json + data.json.gz). Both now use the exact-count idiom already
used by resolveRustInclude and resolveRustEmbeddedFile, preserving
each function's other guards.

Relates to #130

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PEUvjGsJemDFSV8nbxvxBo
Copilot AI lite review requested due to automatic review settings August 27, 2026 16:31

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@JordanCoin
JordanCoin merged commit a754743 into main Aug 27, 2026
12 checks passed
@JordanCoin
JordanCoin deleted the claude/codemap-prs-review-merge-nwifof branch August 27, 2026 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants