Skip to content

Audit foundation: modular supply-evidence contracts and provenance lanes #271

Description

@PhysShell

Classification

Problem

The supply-chain / SourceLink / NuGet provenance idea is useful, but it can easily become a second audit product:

NuGet signatures
packages.lock.json
Package Source Mapping
SourceLink / PDB metadata
SBOM
OSV / Grype / NuGet Audit
OpenSSF Scorecard
SLSA / GitHub attestations / Sigstore
selected rebuild experiments

That is too broad for a single scanner. It would duplicate mature tools, invent another reporting path, and violate the existing Own.NET Audit discipline: orchestrate evidence, normalize it, report it honestly; do not build a new analyzer kingdom.

The correct shape is a modular supply-evidence layer feeding the existing finding identity, taxonomy, evidence ledger and SARIF/report path.

Decision

Define contracts for supply-related evidence as an extension of the audit foundation, not a standalone scanner.

The layer must split cleanly into:

  1. discover — enumerate packages, assemblies, PDBs, lock files, NuGet caches and source roots;
  2. runners — collect exactly one class of evidence each;
  3. evidence records — common versioned output from each runner;
  4. policy evaluation — bans, required provenance, allowlists, black-box classification;
  5. SARIF/report adapter — convert derived findings into the existing audit pipeline.

Runners must not call each other. Runners must not own final policy decisions. Reports must not run tools. 007 must not know individual rule IDs.

Proposed contracts

Evidence record

Add or document a minimal versioned evidence shape compatible with #266/#268:

{
  "schema": "ownaudit.evidence.v1",
  "producer": {
    "name": "sourcelink-debuggability",
    "version": "0.1.0"
  },
  "target": {
    "kind": "assembly",
    "package_id": "Newtonsoft.Json",
    "package_version": "13.0.3",
    "path": "lib/net45/Newtonsoft.Json.dll"
  },
  "input_digest": "sha256:...",
  "config_digest": "sha256:...",
  "source_commit": "...",
  "claims": {},
  "findings": []
}

Required fields should line up with #266 provenance:

producer_run_id
producer_name
producer_version
input_digest
config_digest
source_commit
schema_version

Unknown provenance must remain visible as a coverage limitation, not synthesized.

Rule lanes

Extend #267 with supply/provenance lanes without letting them compete dishonestly with lifetime/correctness findings:

ArtifactProvenance     # PDB, SourceLink, repo URL, commit, symbols
DependencyPolicy       # banned packages, lock file, source mapping, floating versions
KnownVulnerability     # NuGet Audit / OSV / Grype adapter output
RepositoryPosture      # OpenSSF Scorecard adapter output
BuildAttestation       # SLSA / Sigstore / GitHub artifact attestation evidence
SourceCorrespondence   # selected rebuild evidence

These lanes must have independent presentation policy. A missing SourceLink map is useful evidence, not automatically a higher priority than a WPF retained-view leak.

Event vocabulary

Extend #268 with supply-specific events, names reviewable:

ArtifactProvenanceObserved
ArtifactProvenanceRejected
PackageResolutionObserved
PackagePolicyRejected
PackageSignatureVerified
PackageSignatureRejected
SourceLinkMapObserved
SourceLinkChecksumRejected
RepositoryPostureObserved
AttestationObserved
AttestationRejected
RebuildAttempted
RebuildMatched
RebuildMismatched

Initial rule families

SourceLink / debuggability rules

SL001 MissingRepositoryMetadata
SL002 MissingCommitId
SL003 MissingPortablePdb
SL004 MissingSourceLinkMap
SL005 SourceLinkUrlUnreachable
SL006 SourceChecksumMismatch
SL007 PackageHasNoSymbols
SL008 PrivateRepoSourceNotAccessible
SL009 NonDeterministicBuildEvidenceMissing
SL010 ThirdPartyBinaryNoProvenance

Supply policy / correspondence rules

SC001 PackageSignatureMissing
SC002 PackageSignatureInvalid
SC003 PackageNotRepositorySigned
SC004 PackageSourceNotPinned
SC005 LockFileMissing
SC006 RestoreNotLocked
SC007 VulnerablePackage
SC008 MissingRepositoryMetadata
SC009 MissingCommitMetadata
SC010 MissingPortablePdb
SC011 MissingSourceLink
SC012 SourceLinkCommitUnreachable
SC013 ArtifactNotReproducible
SC014 NupkgContainsUnexpectedBinary
SC015 PackageBuiltFromDirtyOrUnknownSource
SC020 RebuildAttempted
SC021 DeterministicRebuildMismatch
SC022 NormalizedDllMismatch
SC023 NupkgContentMismatch

Profiles

Define profiles, not one giant mode:

ci-light:
  nuget-resolution-policy
  sourcelink-debuggability

legacy-wpf:
  ci-light
  explicit black-box classification for DevExpress/closed vendor binaries

incident-response:
  nuget-integrity
  known-vuln
  sbom
  repo-posture
  attestations
  selected rebuild-lab

rebuild-lab:
  selected source-to-artifact correspondence experiments only

Non-goals

  • No new vulnerability database.
  • No SBOM format invention.
  • No package resolver clone.
  • No SourceLink-as-security-proof claim.
  • No rebuild of the NuGet ecosystem.
  • No supply/provenance logic in ownlang/ or the ownership core.
  • No separate OwnAudit report pipeline.
  • No 007 domain logic for SL/SC rules.

Required controls

  1. Removing scorecard does not break sourcelink.
  2. Removing rebuild-lab does not affect ci-light.
  3. A runner cannot call another runner directly.
  4. Unknown/missing provenance is represented as coverage limitation.
  5. Policy reclassification changes derived findings without rewriting raw evidence.
  6. Existing OWN*, XAML*, runtime and static audit semantics do not change.
  7. Supply findings can be emitted to SARIF through the existing normalization/report path.

Acceptance

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions