Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c84426d
Correct native Cargo consumer compilation and generated lint scopes
JeffMusgrave Oct 22, 2026
3c71610
Remove distrusted eMudhra roots from the scanner trust bundle
JeffMusgrave Oct 22, 2026
b053286
Lint governed Cargo replacements and restore forced lint collection
JeffMusgrave Oct 22, 2026
efae918
Omit forced warnings located entirely in external macro bodies
JeffMusgrave Oct 22, 2026
b9e0d7c
Carry a Go 1.26.10 build of Trivy 0.74.0 as the artifact scanner
JeffMusgrave Oct 22, 2026
b73e1f6
Inventory the carried Trivy and its module notices in releases
JeffMusgrave Oct 22, 2026
1c38a42
Carry nested Trivy module notices and validate the exact scanner build
JeffMusgrave Oct 22, 2026
7d0151b
Admit only complete Trivy notice layouts and exact Linux builds
JeffMusgrave Oct 22, 2026
f1edf56
Report pnpm license listing failures in the bundle check
JeffMusgrave Oct 22, 2026
916fbec
Prepare Code Polishy 0.30.1 scanner and Cargo fixes
JeffMusgrave Oct 22, 2026
8bc27c1
Expose the carried scanner guide through the documentation catalog
JeffMusgrave Oct 22, 2026
d787ae3
Refresh expiring dependency assessments with aged TOML fix
JeffMusgrave Oct 23, 2026
956ef87
Merge 0.31.0 and reconcile the scanner release as 0.31.1
JeffMusgrave Oct 23, 2026
3c1c37b
Merge main scanner fix and narrow the Cargo release to 0.31.2
JeffMusgrave Oct 23, 2026
a109b4d
Exclude dependency-cache macro bodies from project warnings
JeffMusgrave Oct 23, 2026
3f09091
Merge remote-tracking branch 'origin/main' into fix/native-rust-accep…
JeffMusgrave Oct 23, 2026
8af44e5
Remove assessments for withdrawn braces advisory
JeffMusgrave Oct 23, 2026
e048892
Merge commit '73f73b799ce9149e8cf1256fd12f1024df670ee8' into fix/nati…
JeffMusgrave Oct 23, 2026
16e419e
Merge main security verification changes and prepare 0.31.3
JeffMusgrave Oct 23, 2026
894de81
Assess Zod collection exhaustion at sealed Knip inputs
JeffMusgrave Oct 23, 2026
0054167
Merge main vulnerability assessment refresh
JeffMusgrave Oct 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.31.3 - 2026-10-23

- Compile and lint governed Cargo replacement packages through their consuming
project, retain forced lint diagnostics, and omit warnings located entirely
inside external macro implementations while preserving caller diagnostics.
- Report the original pnpm failure when JavaScript license listing fails,
instead of treating its error response as a package inventory.

## 0.31.2 - 2026-10-23

- Keep raw package scanner output in report artifacts and show bounded summaries.
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.31.2
0.31.3
66 changes: 56 additions & 10 deletions docs/design/cargo-facts.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,23 +281,69 @@ handwritten lock or disabled source check cannot replace that boundary.

## Compiler checks

Compilation uses the matching pinned cargo-clippy executable directly, with an
absolute Cargo path. This bypasses Cargo's ambient external-subcommand lookup.
Compilation runs the pinned Cargo's `check` with the matching pinned
clippy-driver as `RUSTC_WRAPPER` and the policy lint arguments in
`CLIPPY_ARGS`, the driver interface cargo-clippy itself uses. Cargo-clippy is
not used: it installs the driver only as the workspace wrapper, so path
replacements outside the workspace would compile with plain rustc and escape
Clippy. The wrapper reaches every unit. Cargo still caps lints for registry and
Git packages, and the driver disables Clippy for those capped units, so
non-local code stays silent. Local path dependencies receive the same forced
lints even when they are outside the consumer's workspace; their diagnostics
can therefore refer to source beyond the selected files. The pinned driver is
selected explicitly; there is no ambient external-subcommand lookup.
The common runner captures Cargo's JSON events with bounded output and process
tree cancellation. Cargo must retain its reviewed lock and available dependency
cache through `--frozen`; a missing lock is a preparation failure, never an
invitation for the check to resolve dependencies.

Checks select the manifest's ordinary Cargo packages, default features and all
enabled targets, using the governed native host explicitly. They do not enable
every feature or establish coverage of other target configurations. Compiler
warnings, Clippy's default lint group and unused-code lints use `--force-warn` at
the invocation boundary. Source `allow`, `expect`, `deny` and `forbid` attributes
cannot hide these diagnostics or turn policy lint collection into a compiler
failure. Code Polishy treats the resulting typed findings as blocking errors,
subject to its existing exact exception policy. Failed compilation always adds
a project failure, even when the compiler also reports typed source diagnostics;
an excepted lint cannot make a failed build or operational invocation pass.
every feature or establish coverage of other target configurations.

Compiler selection maps explicitly governed replacement packages to their consumers,
using the same ownership boundary as locked resolution. Discovery retains the
replacement's own metadata for source analysis and also discovers its consumer.
Selecting only replacement source still checks the consumer; selecting both
does not compile it twice. Replacement development targets and their independent
locks are not part of the consumer build. Source analysis remains selected for
the replacement, while compiler evidence covers only dependencies active in the
consumer's default feature and host configuration. Within that configuration,
replacement libraries receive the same Clippy, compiler
warning and unused-code collection as the consumer.

Compiler warnings, Clippy's default lint group and unused-code lints use
`--force-warn` at the invocation boundary. Source `allow`, `expect`, `deny` and
`forbid` attributes, including attributes emitted by macro expansion, cannot
hide these diagnostics or turn policy lint collection into a compiler failure.
Forcing also bypasses rustc's suppression of lints in code generated by
external macros. A warning is therefore omitted when every one of its spans,
at its own location, is macro-expanded text outside project source. The governed
Cargo home contains downloaded registry and Git sources, not project source,
even though it lives under the repository. Both the caller's root spelling and
the physical root spelling retain this distinction. For
example, `std::pin::pin!` of an `async` block reports unreachable code whose
expression and cause both lie in the standard library's macro body. A warning
remains a finding when any span is repository text, including macro input
tokens, a local macro body or the user statement that makes later expanded code
unreachable. Errors are never omitted.

Forcing also overrides the `allow(dead_code)` the test harness adds to a
binary's `main`. That attribute normally seeds dead-code reachability, so the
binary test build reports `main` and everything reachable only from it as
unused. These diagnostics are false and remain unresolved; no exception or
source-parser rule hides them. Cargo's compiler messages carry the same target
identity for the binary and its test build, and rustc reports these items
exactly as it reports a truly unused `cfg(test)` item. Distinguishing them
would require the emitting unit's test mode and either reachability provenance
or the item inventory of the ordinary build. A complete proof that
macro-expanded suppression is otherwise ineffective is also unavailable, so
native admission stays blocked on both.

Code Polishy treats the resulting typed findings as blocking errors, subject to
its existing exact exception policy. Failed compilation always adds a project
failure, even when the compiler also reports typed source diagnostics; an
excepted lint cannot make a failed build or operational invocation pass.
Rust does not support forcing the aggregate `warnings` group. The release owns
the concrete warning-by-default lint inventory for its pinned compiler, checked
against that compiler's advertised lint interface during toolchain tests. Rust
Expand Down
26 changes: 26 additions & 0 deletions internal/quality/cargo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,32 @@ func TestCargoAndGoCheckPlanMatchesObservedCommandOrder(t *testing.T) {
}
}

func TestCargoReplacementCheckKeepsGoCommandsInsideThePlan(t *testing.T) {
t.Parallel()
repo := cargoQualityRepository(t)
repo.Config.SupplyChain.DependencyOverridePolicies = []policy.DependencyOverridePolicy{{Ecosystem: "cargo", Path: "Cargo.toml", Field: "patch.crates-io"}}
writeQualityFile(t, repo.Root, "Cargo.toml", "[package]\nname='app'\nversion='1.0.0'\nedition='2024'\n[workspace]\nexclude=['vendor/library']\n[dependencies]\nlibrary='=1.0.0'\n[patch.crates-io]\nlibrary={path='vendor/library'}\n")
writeQualityFile(t, repo.Root, "Cargo.lock", "version=4\n[[package]]\nname='app'\nversion='1.0.0'\ndependencies=['library']\n[[package]]\nname='library'\nversion='1.0.0'\n")
writeQualityFile(t, repo.Root, "src/lib.rs", "pub fn app() {\n library::call();\n}\n")
writeQualityFile(t, repo.Root, "vendor/library/Cargo.toml", "[package]\nname='library'\nversion='1.0.0'\nedition='2024'\n")
writeQualityFile(t, repo.Root, "vendor/library/src/lib.rs", "pub fn call() {}\n")
writeQualityFile(t, repo.Root, "go.mod", "module example.test/mixed\n\ngo 1.26.6\n")
writeQualityFile(t, repo.Root, "main.go", "package main\n\nfunc main() {}\n")
selection := repository.Selection{Files: []string{"main.go", "src/lib.rs", "vendor/library/src/lib.rs"}}
planned := CheckCommands(repo, selection, "check")
boundary := &cargoRecordingRunner{OSRunner: runner.OSRunner{}}
if findings := Check(t.Context(), repo, selection, boundary, "check"); len(findings) != 0 {
t.Fatalf("replacement prevented the mixed-language check: %+v", findings)
}
want := []string{}
for _, command := range planned {
want = append(want, command.Name)
}
if !reflect.DeepEqual(boundary.names, want) {
t.Fatalf("executed commands = %v, planned = %v", boundary.names, want)
}
}

func TestCargoNativeDeadCodePreservesPublicAPIAndChecksSelectedFeatures(t *testing.T) {
t.Parallel()
repo := cargoQualityRepository(t)
Expand Down
21 changes: 15 additions & 6 deletions internal/rustfacts/compilation.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ func PlanCompilation(repo repository.Repository, discovery DiscoveryPlan, allFil
if len(discovery.Commands) == 0 {
return plan
}
for _, manifest := range discovery.Manifests {
manifests, _, findings := cargoResolutionRoots(repo, discovery.Manifests)
plan.Findings = append(plan.Findings, findings...)
for _, manifest := range manifests {
files := compilationSources(repo, manifest, allFiles)
native, err := repo.NativeUnit(files, "lint", "typecheck", "dead-code")
if err != nil {
Expand Down Expand Up @@ -58,15 +60,22 @@ func compilationSources(repo repository.Repository, manifest string, allFiles []
}

func compilationCommand(repo repository.Repository, manifest string) policy.Command {
command := Command(repo, manifestCommandName("policy-clippy", manifest), "cargo-clippy", "clippy", "--frozen", "--all-targets", "--no-deps", "--message-format=json", "--target", HostTarget(), "--manifest-path", manifest, "--", "--force-warn", "clippy::all", "--force-warn", "unused")
for _, lint := range strings.Fields(compilerWarningLints) {
command.Argv = append(command.Argv, "--force-warn", lint)
}
command := Command(repo, manifestCommandName("policy-clippy", manifest), "cargo", "check", "--frozen", "--all-targets", "--message-format=json", "--target", HostTarget(), "--manifest-path", manifest)
command.Environment = append(command.Environment, "PATH", "LIB", "INCLUDE", "LIBPATH", "SDKROOT", "DEVELOPER_DIR")
command.EnvironmentOverrides = append(command.EnvironmentOverrides, "CARGO="+repo.RustTool("cargo"), "CLIPPY_CONF_DIR="+filepath.Join(repo.PolicyRoot, "tools"))
command.EnvironmentOverrides = append(command.EnvironmentOverrides, "RUSTC_WRAPPER="+repo.RustTool("clippy-driver"), "CLIPPY_ARGS="+strings.Join(compilationLintArguments(), clippyArgumentSeparator)+clippyArgumentSeparator, "CLIPPY_CONF_DIR="+filepath.Join(repo.PolicyRoot, "tools"))
return command
}

func compilationLintArguments() []string {
arguments := []string{"--force-warn", "clippy::all", "--force-warn", "unused"}
for _, lint := range strings.Fields(compilerWarningLints) {
arguments = append(arguments, "--force-warn", lint)
}
return arguments
}

const clippyArgumentSeparator = "__CLIPPY_HACKERY__"

func HostTarget() string {
architecture := map[string]string{"amd64": "x86_64", "arm64": "aarch64"}[runtime.GOARCH]
platform := map[string]string{"linux": "unknown-linux-gnu", "darwin": "apple-darwin", "windows": "pc-windows-msvc"}[runtime.GOOS]
Expand Down
100 changes: 100 additions & 0 deletions internal/rustfacts/compilation_patches_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package rustfacts

import (
"bytes"
"os"
"os/exec"
"path/filepath"
"slices"
"testing"

"github.com/riteofstring/code-polishy/internal/policy"
"github.com/riteofstring/code-polishy/internal/repository"
"github.com/riteofstring/code-polishy/internal/runner"
)

func TestRustCompilationUsesReplacementConsumerAndPreservesDependencyTargets(t *testing.T) {
t.Parallel()
for _, selected := range []string{"Cargo.toml", "vendor/patch-source/src/lib.rs", "vendor/leaf/src/lib.rs"} {
t.Run(selected, func(t *testing.T) {
repo := consumedReplacementRepository(t)
write(t, repo.Root, "vendor/patch-source/src/lib.rs", "pub fn value() -> u32 { patch_leaf::value() }\n")
write(t, repo.Root, "vendor/leaf/src/lib.rs", "pub fn value() -> u32 { 42 }\n")
before := readRustFile(t, repo, "Cargo.lock")
plan, discovery := compilationDiscovery(t, repo, selected)
if findings := Compile(t.Context(), repo, plan, discovery, runner.OSRunner{}); len(findings) != 0 {
t.Fatalf("consumer compilation failed: %+v", findings)
}
if !bytes.Equal(before, readRustFile(t, repo, "Cargo.lock")) {
t.Fatal("compilation changed the consumer lock")
}
for _, path := range []string{"vendor/patch-source/Cargo.lock", "vendor/leaf/Cargo.lock"} {
if _, err := os.Stat(filepath.Join(repo.Root, filepath.FromSlash(path))); !os.IsNotExist(err) {
t.Fatalf("compilation created a replacement lock at %s: %v", path, err)
}
}
write(t, repo.Root, "vendor/leaf/src/lib.rs", "pub fn value() -> u32 { \"wrong\" }\n")
findings := Compile(t.Context(), repo, plan, discovery, runner.OSRunner{})
if !slices.ContainsFunc(findings, func(f policy.Finding) bool {
return f.Check == "quality.rustCompiler" && f.Subject == "E0308" && f.Path == "vendor/leaf/src/lib.rs"
}) {
t.Fatalf("consumer failed to check the replacement source: %+v", findings)
}
})
}
}

func TestRustCompilationLintsGovernedReplacementsAndCapsNonLocalDependencies(t *testing.T) {
t.Parallel()
repo := consumedReplacementRepository(t)
remote := t.TempDir()
write(t, remote, "Cargo.toml", "[package]\nname='remote'\nversion='1.0.0'\nedition='2021'\n")
write(t, remote, "src/lib.rs", `pub fn value() -> u32 { if needless(true) { 1 } else { 2 } }
fn needless(value: bool) -> bool { if value { true } else { false } }
fn remote_unused() {}
#[macro_export]
macro_rules! remote_stop { () => {{ return 0u32; 1u32 }}; }
`)
for _, arguments := range [][]string{{"init", "-q"}, {"add", "."}, {"-c", "user.name=fixture", "-c", "user.email=fixture@example.test", "commit", "-qm", "fixture"}} {
if output, err := exec.Command("git", append([]string{"-C", remote}, arguments...)...).CombinedOutput(); err != nil {
t.Fatalf("git fixture: %v; %s", err, output)
}
}
manifest := string(readRustFile(t, repo, "Cargo.toml"))
write(t, repo.Root, "Cargo.toml", string(bytes.Replace([]byte(manifest), []byte("[patch.crates-io]"), []byte("remote={git='file://"+filepath.ToSlash(remote)+"'}\n[patch.crates-io]"), 1)))
write(t, repo.Root, "src/lib.rs", "pub fn value() -> u32 { patch_source::value() + remote::value() }\npub fn remote_macro() -> u32 { remote::remote_stop!() }\n")
write(t, repo.Root, "vendor/patch-source/src/lib.rs", "pub fn value() -> u32 { if needless(true) { patch_leaf::value() } else { 2 } }\nfn needless(value: bool) -> bool { if value { true } else { false } }\n#[allow(dead_code)]\nfn source_unused() {}\n")
write(t, repo.Root, "vendor/leaf/src/lib.rs", "macro_rules! quiet { ($i:item) => { #[allow(dead_code, clippy::needless_bool)] $i }; }\nquiet! { fn leaf_needless(value: bool) -> bool { if value { true } else { false } } }\npub fn value() -> u32 { 42 }\n")
lock := exec.Command(repo.RustTool("cargo"), "generate-lockfile", "--manifest-path", filepath.Join(repo.Root, "Cargo.toml"))
lock.Env = append(os.Environ(), "CARGO_HOME="+CargoHome(repo), "RUSTC="+repo.RustTool("rustc"))
if output, err := lock.CombinedOutput(); err != nil {
t.Fatalf("fixture lock: %v; %s", err, output)
}
plan, discovery := compilationDiscovery(t, repo, "vendor/patch-source/src/lib.rs")
reported := [][3]string{}
for _, finding := range Compile(t.Context(), repo, plan, discovery, runner.OSRunner{}) {
reported = append(reported, [3]string{finding.Check, finding.Subject, finding.Path})
}
slices.SortFunc(reported, func(left, right [3]string) int { return slices.Compare(left[:], right[:]) })
reported = slices.Compact(reported)
want := [][3]string{
{"quality.clippy", "clippy::needless_bool", "vendor/leaf/src/lib.rs"},
{"quality.clippy", "clippy::needless_bool", "vendor/patch-source/src/lib.rs"},
{"quality.rustCompiler", "dead_code", "vendor/leaf/src/lib.rs"},
{"quality.rustCompiler", "dead_code", "vendor/patch-source/src/lib.rs"},
}
if !slices.Equal(reported, want) {
t.Fatalf("replacement lint findings = %v, want %v", reported, want)
}
}

func consumedReplacementRepository(t *testing.T) repository.Repository {
t.Helper()
repo := cargoPatchRepository(t)
manifest := string(readRustFile(t, repo, "Cargo.toml"))
write(t, repo.Root, "Cargo.toml", string(bytes.ReplaceAll([]byte(manifest), []byte("default=[]"), []byte("default=['desktop']"))))
write(t, repo.Root, "src/lib.rs", "pub fn value() -> u32 { patch_source::value() }\n")
write(t, repo.Root, "vendor/patch-source/build.rs", "fn main() {}\n")
write(t, repo.Root, "vendor/patch-source/tests/unconsumed.rs", "compile_error!(\"dependency development targets must not compile\");\n")
return repo
}
28 changes: 28 additions & 0 deletions internal/rustfacts/compilation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"context"
"errors"
"fmt"
"os"
"path/filepath"
"slices"
Expand Down Expand Up @@ -61,6 +62,9 @@ func TestRustCompilationCollectsLintsDespiteSourceLevels(t *testing.T) {
"allow unused": {"#[allow(dead_code)]\nfn unused() {}\npub fn answer() {}\n", "dead_code"},
"expect unused": {"#[expect(dead_code)]\nfn unused() {}\npub fn answer() {}\n", "dead_code"},
"allow warning": {"#[allow(unreachable_code)]\npub fn answer() { return; println!(\"unreachable\"); }\n", "unreachable_code"},
"macro clippy": {"macro_rules! quiet { ($i:item) => { #[allow(dead_code, clippy::needless_bool)] $i }; }\nquiet! { fn unused(value: bool) -> bool { if value { true } else { false } } }\npub fn answer() {}\n", "clippy::needless_bool"},
"macro unused": {"macro_rules! quiet { ($i:item) => { #[allow(dead_code, clippy::needless_bool)] $i }; }\nquiet! { fn unused(value: bool) -> bool { if value { true } else { false } } }\npub fn answer() {}\n", "dead_code"},
"meta unused": {"macro_rules! with { ($m:meta, $i:item) => { #[$m] $i }; }\nwith!(allow(dead_code), fn unused() {});\npub fn answer() {}\n", "dead_code"},
} {
t.Run(name, func(t *testing.T) {
repo := compilationRepository(t, test.source)
Expand All @@ -82,6 +86,30 @@ func TestRustCompilationCollectsLintsDespiteSourceLevels(t *testing.T) {
}
}

func TestRustCompilationOmitsLibraryExpansionWarningsAndKeepsRepositoryCode(t *testing.T) {
t.Parallel()
repo := compilationRepository(t, `macro_rules! stop { () => {{ return 0; 1 }} }
pub fn local_macro() -> u32 { stop!() }
pub fn after_todo() -> u32 { todo!(); 1 }
fn really_unused() {}
#[cfg(test)]
fn test_helper_unused() {}
pub fn pinned() -> usize { let future = std::pin::pin!(async { 1u32 }); std::mem::size_of_val(&future) }
pub fn pinned_input() -> usize { let future = std::pin::pin!(async { return 1u32; 2u32 }); std::mem::size_of_val(&future) }
`)
plan, discovery := compilationDiscovery(t, repo, "src/lib.rs")
reported := []string{}
for _, finding := range Compile(t.Context(), repo, plan, discovery, runner.OSRunner{}) {
reported = append(reported, fmt.Sprintf("%s %s:%d", finding.Subject, finding.Path, finding.Line))
}
slices.Sort(reported)
reported = slices.Compact(reported)
want := []string{"dead_code src/lib.rs:4", "dead_code src/lib.rs:6", "unreachable_code src/lib.rs:1", "unreachable_code src/lib.rs:3", "unreachable_code src/lib.rs:8"}
if !slices.Equal(reported, want) {
t.Fatalf("findings = %v, want %v", reported, want)
}
}

func TestRustCompilationFailureCannotBecomeAnExceptableLint(t *testing.T) {
t.Parallel()
for name, test := range map[string]struct{ source, build, subject string }{
Expand Down
29 changes: 29 additions & 0 deletions internal/rustfacts/compiler_diagnostics.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func compilerFindings(repo repository.Repository, manifest string, workspace Wor
default:
return nil, errors.New("cargo compiler diagnostic has an unsupported severity")
}
if diagnostic.Level == "warning" && externalExpansion(repo, workspace, diagnostic.Spans) {
return nil, nil
}
code, check := "rustc", "quality.rustCompiler"
if diagnostic.Code != nil && diagnostic.Code.Code != "" {
code = diagnostic.Code.Code
Expand Down Expand Up @@ -74,3 +77,29 @@ func compilerLocation(repo repository.Repository, workspace Workspace, span comp
}
return policy.FindingLocation{}, false
}

func externalExpansion(repo repository.Repository, workspace Workspace, spans []compilerSpan) bool {
primary := false
for _, span := range spans {
path := span.File
if !filepath.IsAbs(path) {
path = filepath.Join(repo.Root, filepath.FromSlash(workspace.Root), path)
}
if span.Expansion == nil || repositorySource(repo, path) {
return false
}
primary = primary || span.Primary
}
return primary
}

func repositorySource(repo repository.Repository, path string) bool {
physical, _ := filepath.EvalSymlinks(repo.Root)
for _, root := range []string{repo.Root, physical} {
if root != "" && withinDirectory(root, path) {
repo.Root = root
return !withinDirectory(CargoHome(repo), path)
}
}
return false
}
Loading
Loading