<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: neve7r</title>
    <description>The latest articles on Forem by neve7r (@neve7er).</description>
    <link>https://forem.com/neve7er</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3912490%2F41ae4161-56d3-4685-922c-f351a17d4e45.png</url>
      <title>Forem: neve7r</title>
      <link>https://forem.com/neve7er</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/neve7er"/>
    <language>en</language>
    <item>
      <title>The supply chain evidence package your SOC 2 auditor actually wants.</title>
      <dc:creator>neve7r</dc:creator>
      <pubDate>Mon, 11 May 2026 06:39:07 +0000</pubDate>
      <link>https://forem.com/neve7er/the-supply-chain-evidence-package-your-soc-2-auditor-actually-wants-h81</link>
      <guid>https://forem.com/neve7er/the-supply-chain-evidence-package-your-soc-2-auditor-actually-wants-h81</guid>
      <description>&lt;h2&gt;
  
  
  The Email Nobody Wants
&lt;/h2&gt;

&lt;p&gt;It usually starts with a completely normal message.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Can you provide evidence of your software supply chain controls?”&lt;/p&gt;

&lt;p&gt;“Do you maintain SBOMs for production artifacts?”&lt;/p&gt;

&lt;p&gt;“How do you track vulnerability exceptions over time?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first glance, this sounds manageable. You already run &lt;code&gt;npm audit&lt;/code&gt;. Maybe you use Dependabot. Maybe your CI blocks critical vulnerabilities. Your dashboards are green. CVE counts are low.&lt;/p&gt;

&lt;p&gt;Then the auditor asks the next question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Can you prove that this report corresponds to what was actually deployed?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And suddenly the entire room gets quiet.&lt;/p&gt;

&lt;p&gt;Because most teams don't actually have &lt;em&gt;evidence&lt;/em&gt;. They have snapshots:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a vulnerability scan from last month&lt;/li&gt;
&lt;li&gt;a Syft export from one container image&lt;/li&gt;
&lt;li&gt;a spreadsheet full of accepted risks&lt;/li&gt;
&lt;li&gt;screenshots from CI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What auditors want is something much stricter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a reproducible inventory of dependencies&lt;/li&gt;
&lt;li&gt;tied to deployed artifacts&lt;/li&gt;
&lt;li&gt;with documented risk decisions&lt;/li&gt;
&lt;li&gt;and a traceable history of exceptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not “we scanned it once.”&lt;br&gt;
Not “GitHub said it was fine.”&lt;br&gt;
Not “our CVE count is low.”&lt;/p&gt;

&lt;p&gt;They want a chain of evidence.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Real Problem Is Not Vulnerabilities
&lt;/h1&gt;

&lt;p&gt;Most engineers assume the audit is about security findings.&lt;/p&gt;

&lt;p&gt;It usually isn't.&lt;/p&gt;

&lt;p&gt;The real problem is &lt;em&gt;reproducibility&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Imagine this conversation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“This SBOM doesn't match the deployed digest.”&lt;/p&gt;

&lt;p&gt;“This image was rebuilt.”&lt;/p&gt;

&lt;p&gt;“This exception has no expiration.”&lt;/p&gt;

&lt;p&gt;“Nobody remembers why we accepted this risk.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is what actually fails audits.&lt;/p&gt;

&lt;p&gt;The issue is not whether you scanned your dependencies.&lt;/p&gt;

&lt;p&gt;The issue is whether your decisions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explainable&lt;/li&gt;
&lt;li&gt;reproducible&lt;/li&gt;
&lt;li&gt;traceable&lt;/li&gt;
&lt;li&gt;reviewable months later&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  What Auditors Actually Want
&lt;/h1&gt;

&lt;p&gt;Most compliance frameworks dance around the wording, but the underlying requirements are surprisingly consistent.&lt;/p&gt;

&lt;p&gt;Your auditor usually wants evidence for four things:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;What they actually mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dependency visibility&lt;/td&gt;
&lt;td&gt;“Can you enumerate what shipped?”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vulnerability management&lt;/td&gt;
&lt;td&gt;“Did you evaluate known issues?”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risk acceptance process&lt;/td&gt;
&lt;td&gt;“Who approved exceptions and why?”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Traceability&lt;/td&gt;
&lt;td&gt;“Can you tie this evidence to production?”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The frustrating part is that many security tools optimize for &lt;em&gt;detection&lt;/em&gt;, not &lt;em&gt;evidence integrity&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A scanner tells you something is vulnerable.&lt;/p&gt;

&lt;p&gt;An auditor asks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why was it accepted?&lt;/li&gt;
&lt;li&gt;when was that decision made?&lt;/li&gt;
&lt;li&gt;who approved it?&lt;/li&gt;
&lt;li&gt;is the decision still valid?&lt;/li&gt;
&lt;li&gt;can you reproduce the report today?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are different problems.&lt;/p&gt;




&lt;h1&gt;
  
  
  The “Spreadsheet Hell” Phase
&lt;/h1&gt;

&lt;p&gt;Almost every growing team goes through the same progression:&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 1 — “We’ll just use npm audit”
&lt;/h3&gt;

&lt;p&gt;Simple enough.&lt;/p&gt;

&lt;p&gt;Until you get hundreds of transitive findings nobody understands.&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 2 — “We’ll suppress the noisy stuff”
&lt;/h3&gt;

&lt;p&gt;Now you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;undocumented ignores&lt;/li&gt;
&lt;li&gt;permanent suppressions&lt;/li&gt;
&lt;li&gt;exceptions nobody revisits&lt;/li&gt;
&lt;li&gt;tribal knowledge&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Phase 3 — “We need an audit trail”
&lt;/h3&gt;

&lt;p&gt;Now someone creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an exception spreadsheet&lt;/li&gt;
&lt;li&gt;vulnerability review meetings&lt;/li&gt;
&lt;li&gt;manual SBOM exports&lt;/li&gt;
&lt;li&gt;ticket templates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And suddenly security work becomes document management.&lt;/p&gt;




&lt;h3&gt;
  
  
  Phase 4 — The Audit
&lt;/h3&gt;

&lt;p&gt;This is where the cracks show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SBOM doesn’t match deployed image&lt;/li&gt;
&lt;li&gt;reports aren’t reproducible&lt;/li&gt;
&lt;li&gt;exception rationale is missing&lt;/li&gt;
&lt;li&gt;evidence exists in 14 places&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the issue is operational entropy, not scanning capability.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Supply Chain Evidence Package
&lt;/h1&gt;

&lt;p&gt;So what does a defensible evidence package actually look like?&lt;/p&gt;

&lt;p&gt;At minimum:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. A reproducible SBOM
&lt;/h2&gt;

&lt;p&gt;Not a random export from a laptop.&lt;/p&gt;

&lt;p&gt;A generated artifact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tied to CI&lt;/li&gt;
&lt;li&gt;tied to a commit&lt;/li&gt;
&lt;li&gt;tied to a deployment digest&lt;/li&gt;
&lt;li&gt;versioned&lt;/li&gt;
&lt;li&gt;reproducible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Formats like CycloneDX help because they standardize structure.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Machine-readable risk decisions
&lt;/h2&gt;

&lt;p&gt;This is where most pipelines fail.&lt;/p&gt;

&lt;p&gt;A CVSS score is not a decision.&lt;/p&gt;

&lt;p&gt;“Critical” is not an action plan.&lt;/p&gt;

&lt;p&gt;You need explicit classifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dev-only&lt;/li&gt;
&lt;li&gt;optional&lt;/li&gt;
&lt;li&gt;transitive&lt;/li&gt;
&lt;li&gt;direct + unpatched&lt;/li&gt;
&lt;li&gt;exempted with approval&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is not the label itself.&lt;/p&gt;

&lt;p&gt;The important part is that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the vocabulary is finite&lt;/li&gt;
&lt;li&gt;the logic is documented&lt;/li&gt;
&lt;li&gt;the output is reproducible&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Expiring exceptions
&lt;/h2&gt;

&lt;p&gt;A permanent exception is just forgotten risk.&lt;/p&gt;

&lt;p&gt;Every suppression should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;justification&lt;/li&gt;
&lt;li&gt;owner&lt;/li&gt;
&lt;li&gt;expiration date&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Otherwise nobody remembers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why it existed&lt;/li&gt;
&lt;li&gt;whether it is still valid&lt;/li&gt;
&lt;li&gt;whether the vulnerability changed&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Deterministic output
&lt;/h2&gt;

&lt;p&gt;This matters more than most teams realize.&lt;/p&gt;

&lt;p&gt;If:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the same lockfile&lt;/li&gt;
&lt;li&gt;on the same commit&lt;/li&gt;
&lt;li&gt;with the same policy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;can generate different results over time…&lt;/p&gt;

&lt;p&gt;…then your audit evidence is unstable.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;auditors cannot reproduce it&lt;/li&gt;
&lt;li&gt;diffs become meaningless&lt;/li&gt;
&lt;li&gt;trust erodes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reproducibility is not a “nice to have.”&lt;br&gt;
It is the foundation of defensible compliance evidence.&lt;/p&gt;




&lt;h1&gt;
  
  
  Why We Started Building audit-ready
&lt;/h1&gt;

&lt;p&gt;This was the motivation behind &lt;code&gt;audit-ready&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Let’s build another vulnerability scanner.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do we make audit decisions reproducible?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The design constraints became unusually strict:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deterministic core logic&lt;/li&gt;
&lt;li&gt;no environment-dependent behavior&lt;/li&gt;
&lt;li&gt;explicit machine-readable &lt;code&gt;reasonCode&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;time-bounded exceptions&lt;/li&gt;
&lt;li&gt;schema-validated SBOM output&lt;/li&gt;
&lt;li&gt;reproducible triage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was to make outputs defensible later — not just readable today.&lt;/p&gt;




&lt;h1&gt;
  
  
  One Small Architectural Decision That Changed Everything
&lt;/h1&gt;

&lt;p&gt;The most important design choice ended up being surprisingly simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every dependency gets exactly one &lt;code&gt;reasonCode&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not a floating score.&lt;br&gt;
Not an opaque priority.&lt;/p&gt;

&lt;p&gt;A deterministic classification like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DEV_DEPENDENCY_ONLY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TRANSITIVE_NO_EXPLOIT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DIRECT_UNPATCHED&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EXEMPTED&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This made several things suddenly possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI enforcement (&lt;code&gt;--fail-on&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;stable audit reports&lt;/li&gt;
&lt;li&gt;diffable results&lt;/li&gt;
&lt;li&gt;reproducible rationale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The report stopped being:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Here are 187 scary findings.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And became:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Here are the 3 decisions requiring action.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  What We Learned
&lt;/h1&gt;

&lt;p&gt;A few surprising things emerged while building this:&lt;/p&gt;

&lt;h3&gt;
  
  
  Auditors care more about consistency than sophistication
&lt;/h3&gt;

&lt;p&gt;A simple, reproducible rule system is often more useful than a smarter-but-opaque scoring engine.&lt;/p&gt;




&lt;h3&gt;
  
  
  Most security debt is actually process debt
&lt;/h3&gt;

&lt;p&gt;Teams often know vulnerabilities exist.&lt;/p&gt;

&lt;p&gt;The real issue is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing ownership&lt;/li&gt;
&lt;li&gt;undocumented exceptions&lt;/li&gt;
&lt;li&gt;broken traceability&lt;/li&gt;
&lt;li&gt;inconsistent evidence&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  “Low CVE count” is not evidence
&lt;/h3&gt;

&lt;p&gt;You can have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0 critical findings&lt;/li&gt;
&lt;li&gt;and still fail an audit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;because you cannot explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how decisions were made&lt;/li&gt;
&lt;li&gt;whether reports are reproducible&lt;/li&gt;
&lt;li&gt;whether evidence maps to production&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Honest Limitations
&lt;/h1&gt;

&lt;p&gt;There are still major gaps.&lt;/p&gt;

&lt;p&gt;Current limitations include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm only&lt;/li&gt;
&lt;li&gt;no monorepo support yet&lt;/li&gt;
&lt;li&gt;reachability analysis is heuristic&lt;/li&gt;
&lt;li&gt;no caching yet (Phase 3)&lt;/li&gt;
&lt;li&gt;patch availability depends on OSV metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And importantly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deterministic logic means no “smart guesses”&lt;/li&gt;
&lt;li&gt;if no rule matches, the tool fails explicitly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That tradeoff is intentional.&lt;/p&gt;

&lt;p&gt;An incorrect deterministic answer is easier to audit than an unverifiable heuristic one.&lt;/p&gt;




&lt;h1&gt;
  
  
  If Your Audit Starts Next Week
&lt;/h1&gt;

&lt;p&gt;If you are suddenly being asked for supply chain evidence, the immediate goal is not perfection.&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;reproducibility&lt;/li&gt;
&lt;li&gt;traceability&lt;/li&gt;
&lt;li&gt;documented decisions&lt;/li&gt;
&lt;li&gt;expiring exceptions&lt;/li&gt;
&lt;li&gt;artifact-to-deployment linkage&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even partial automation helps enormously if it is consistent.&lt;/p&gt;

&lt;p&gt;Because the hardest thing to defend in an audit is not vulnerability presence.&lt;/p&gt;

&lt;p&gt;It is undocumented inconsistency.&lt;/p&gt;




&lt;h1&gt;
  
  
  Closing
&lt;/h1&gt;

&lt;p&gt;Supply chain security is slowly shifting from:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Did you scan your dependencies?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Can you prove your decisions?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are fundamentally different requirements.&lt;/p&gt;

&lt;p&gt;And most existing workflows were designed for the first one.&lt;/p&gt;

&lt;p&gt;Not the second.&lt;/p&gt;




&lt;p&gt;&lt;code&gt;audit-ready&lt;/code&gt; is currently in beta (Phase 3 complete). We are actively looking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;real-world CI/CD edge cases&lt;/li&gt;
&lt;li&gt;audit workflow feedback&lt;/li&gt;
&lt;li&gt;reproducibility failures&lt;/li&gt;
&lt;li&gt;incorrect triage assumptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your team has dealt with SBOM audits, compliance evidence drift, or vulnerability exception chaos, I’d genuinely love feedback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/neve7er/audit-ready-sbom-kit" rel="noopener noreferrer"&gt;https://github.com/neve7er/audit-ready-sbom-kit&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>opensource</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>"Why I stopped trusting npm audit (and built my own)"</title>
      <dc:creator>neve7r</dc:creator>
      <pubDate>Mon, 04 May 2026 17:42:52 +0000</pubDate>
      <link>https://forem.com/neve7er/why-i-stopped-trusting-npm-audit-and-built-my-own-12d3</link>
      <guid>https://forem.com/neve7er/why-i-stopped-trusting-npm-audit-and-built-my-own-12d3</guid>
      <description>&lt;p&gt;Generate a CycloneDX SBOM and deterministic, audit-ready risk report from your package-lock.json.&lt;/p&gt;

&lt;p&gt;You run npm audit. It says “47 vulnerabilities.”&lt;/p&gt;

&lt;p&gt;Cool.&lt;/p&gt;

&lt;p&gt;Which ones actually matter?&lt;/p&gt;

&lt;p&gt;The one in your production bundle?&lt;br&gt;
The dev-only Jest dependency?&lt;br&gt;
The transitive package you didn’t even know existed?&lt;/p&gt;

&lt;p&gt;You don’t know.&lt;/p&gt;

&lt;p&gt;So you either:&lt;/p&gt;

&lt;p&gt;Ignore everything → ship anyway&lt;br&gt;
Or block everything → break your team&lt;/p&gt;

&lt;p&gt;Either way, you lose signal.&lt;/p&gt;

&lt;p&gt;The real problem isn’t vulnerabilities — it’s decision-making&lt;/p&gt;

&lt;p&gt;Most tools answer:&lt;/p&gt;

&lt;p&gt;“What is wrong?”&lt;/p&gt;

&lt;p&gt;They don’t answer:&lt;/p&gt;

&lt;p&gt;“What should I do about it?”&lt;br&gt;
“Can I prove that decision later?”&lt;/p&gt;

&lt;p&gt;That last one is the real problem.&lt;/p&gt;

&lt;p&gt;Enter: audit-ready&lt;/p&gt;

&lt;p&gt;Instead of scores, it gives you decisions.&lt;/p&gt;

&lt;p&gt;Deterministic. Reproducible. Auditable.&lt;/p&gt;

&lt;p&gt;🔑 reasonCode replaces CVSS&lt;/p&gt;

&lt;p&gt;Every dependency gets exactly one label:&lt;/p&gt;

&lt;p&gt;DEV_DEPENDENCY_ONLY&lt;br&gt;
OPTIONAL_DEPENDENCY&lt;br&gt;
TRANSITIVE_NO_EXPLOIT&lt;br&gt;
DIRECT_UNPATCHED&lt;br&gt;
NO_KNOWN_VULNERABILITY&lt;br&gt;
EXEMPTED&lt;/p&gt;

&lt;p&gt;No interpretation required.&lt;/p&gt;

&lt;p&gt;CI becomes trivial&lt;br&gt;
npx audit-ready scan --fail-on DIRECT_UNPATCHED&lt;br&gt;
Exit 0 → safe&lt;br&gt;
Exit 1 → actionable issue&lt;/p&gt;

&lt;p&gt;Not “7 high vulnerabilities.”&lt;br&gt;
👉 A clear, enforceable rule&lt;/p&gt;

&lt;p&gt;🧠 The constraint that shapes everything&lt;/p&gt;

&lt;p&gt;Same package-lock.json → identical output. Always.&lt;/p&gt;

&lt;p&gt;How that’s enforced&lt;/p&gt;

&lt;p&gt;Core logic has hard constraints:&lt;/p&gt;

&lt;p&gt;no Date&lt;br&gt;
no Math.random()&lt;br&gt;
no process.env&lt;br&gt;
no I/O&lt;/p&gt;

&lt;p&gt;And yes, it’s enforced by test:&lt;/p&gt;

&lt;p&gt;const banned = ['Date', 'Date.now()', 'Math.random()', 'process.env'];&lt;br&gt;
expect(found).toHaveLength(0);&lt;/p&gt;

&lt;p&gt;If determinism breaks → build fails.&lt;/p&gt;

&lt;p&gt;⚙️ The engine is intentionally simple&lt;br&gt;
for (const rule of rules) {&lt;br&gt;
  if (rule.match(node)) {&lt;br&gt;
    return { ...node, reasonCode: rule.reasonCode }&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;No scoring. No heuristics.&lt;/p&gt;

&lt;p&gt;👉 First match wins&lt;/p&gt;

&lt;p&gt;Priority    Rule&lt;br&gt;
1   NO_KNOWN_VULNERABILITY&lt;br&gt;
2   DEV_DEPENDENCY_ONLY&lt;br&gt;
3   OPTIONAL_DEPENDENCY&lt;br&gt;
4   TRANSITIVE_NO_EXPLOIT&lt;br&gt;
5   DIRECT_UNPATCHED&lt;/p&gt;

&lt;p&gt;Order = logic.&lt;/p&gt;

&lt;p&gt;🧾 Output you can actually use&lt;br&gt;
CycloneDX 1.5 SBOM&lt;br&gt;
Human-readable report&lt;br&gt;
SARIF (GitHub Security)&lt;/p&gt;

&lt;p&gt;Everything tied to reasonCode.&lt;/p&gt;

&lt;p&gt;🔐 Security: this tool audits itself&lt;/p&gt;

&lt;p&gt;If you’re generating audit artifacts, your tool has to be trustworthy.&lt;/p&gt;

&lt;p&gt;Here’s what that means in practice:&lt;/p&gt;

&lt;p&gt;No environment access&lt;/p&gt;

&lt;p&gt;The core engine literally cannot read:&lt;/p&gt;

&lt;p&gt;environment variables&lt;br&gt;
system time&lt;br&gt;
runtime context&lt;/p&gt;

&lt;p&gt;👉 Output depends only on input + tool version&lt;/p&gt;

&lt;p&gt;Deterministic PURL generation&lt;/p&gt;

&lt;p&gt;Standard encoders (encodeURIComponent, URL) can differ across Node versions.&lt;/p&gt;

&lt;p&gt;So PURLs are built manually.&lt;/p&gt;

&lt;p&gt;👉 Same package → same PURL → always&lt;/p&gt;

&lt;p&gt;Schema validation (input + output)&lt;br&gt;
.audit-policy.json → validated before scan&lt;br&gt;
SBOM → validated before write&lt;/p&gt;

&lt;p&gt;If validation fails:&lt;/p&gt;

&lt;p&gt;👉 Nothing is written&lt;/p&gt;

&lt;p&gt;Immutable output&lt;br&gt;
All models are readonly&lt;br&gt;
Everything is Object.freeze()d&lt;/p&gt;

&lt;p&gt;👉 No silent mutation&lt;br&gt;
👉 No post-processing surprises&lt;/p&gt;

&lt;p&gt;Exceptions cannot live forever&lt;/p&gt;

&lt;p&gt;Every exception requires:&lt;/p&gt;

&lt;p&gt;a reason&lt;br&gt;
an expiration date&lt;/p&gt;

&lt;p&gt;Expired?&lt;/p&gt;

&lt;p&gt;audit-ready audit-exceptions&lt;/p&gt;

&lt;p&gt;👉 exit 1&lt;/p&gt;

&lt;p&gt;No silent ignores.&lt;/p&gt;

&lt;p&gt;Network safety by design&lt;/p&gt;

&lt;p&gt;Only one external call:&lt;/p&gt;

&lt;p&gt;👉 OSV API with PURLs&lt;/p&gt;

&lt;p&gt;If it fails:&lt;/p&gt;

&lt;p&gt;SBOM still generated&lt;br&gt;
tool exits with code 2&lt;br&gt;
no retries, no stale cache&lt;br&gt;
Self-audit (this is rare)&lt;br&gt;
audit-ready audit-self&lt;/p&gt;

&lt;p&gt;The tool runs its own pipeline on itself.&lt;/p&gt;

&lt;p&gt;Same code. Same rules.&lt;/p&gt;

&lt;p&gt;👉 If it lies, it exposes itself.&lt;/p&gt;

&lt;p&gt;⚠️ What this tool does NOT do&lt;br&gt;
No AI explanations&lt;br&gt;
No “smart” guessing&lt;br&gt;
No monorepo support (yet)&lt;br&gt;
No caching (Phase 3)&lt;br&gt;
npm only&lt;/p&gt;

&lt;p&gt;If a case isn’t covered:&lt;/p&gt;

&lt;p&gt;👉 it fails loudly&lt;/p&gt;

&lt;p&gt;Why this matters&lt;/p&gt;

&lt;p&gt;This isn’t about better scanning.&lt;/p&gt;

&lt;p&gt;It’s about:&lt;/p&gt;

&lt;p&gt;reproducible decisions&lt;br&gt;
CI you can trust&lt;br&gt;
audit trails you can defend&lt;br&gt;
🧪 Try it&lt;br&gt;
npx audit-ready@beta scan --dry-run&lt;br&gt;
🧭 Status&lt;br&gt;
Phase 1: SBOM + triage ✅&lt;br&gt;
Phase 2: policy + exceptions ✅&lt;br&gt;
Phase 3: caching + performance 🚧&lt;/p&gt;

&lt;p&gt;Production release planned after Phase 3.&lt;/p&gt;

&lt;p&gt;💬 Looking for feedback&lt;br&gt;
weird dependency graphs&lt;br&gt;
incorrect classifications&lt;br&gt;
CI edge cases&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/neve7er/audit-ready" rel="noopener noreferrer"&gt;https://github.com/neve7er/audit-ready&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Final thought&lt;/p&gt;

&lt;p&gt;Most tools try to be smart.&lt;/p&gt;

&lt;p&gt;This one tries to be predictable.&lt;/p&gt;

&lt;p&gt;Because in security:&lt;/p&gt;

&lt;p&gt;predictability beats intelligence.&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>npm</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
