<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>SPDX on Sven Ruppert</title><link>https://svenruppert.com/tags/spdx/</link><description>Sven Ruppert — Java Veteran, Speaker, Trainer &amp; Bushcrafter. Articles, talks, workshops and videos on Core Java, Cybersecurity, Vaadin and Developer Relations.</description><generator>Hugo</generator><language>en</language><managingEditor>sven.ruppert@gmail.com (Sven Ruppert)</managingEditor><webMaster>sven.ruppert@gmail.com (Sven Ruppert)</webMaster><copyright>© 2026 Sven Ruppert</copyright><atom:link href="https://svenruppert.com/tags/spdx/index.xml" rel="self" type="application/rss+xml"/><image><url>https://svenruppert.com/img/sven-ruppert.jpg</url><title>Sven Ruppert</title><link>https://svenruppert.com/tags/spdx/</link></image><lastBuildDate>Thu, 24 Sep 2026 10:00:00 +0200</lastBuildDate><item><title>What an SBOM Reveals When You Ask It</title><link>https://svenruppert.com/posts/what-an-sbom-reveals-when-you-ask-it/</link><pubDate>Thu, 24 Sep 2026 10:00:00 +0200</pubDate><author>sven.ruppert@gmail.com (Sven Ruppert)</author><dc:creator>Sven Ruppert</dc:creator><guid isPermaLink="true">https://svenruppert.com/posts/what-an-sbom-reveals-when-you-ask-it/</guid><description>Querying an SBOM for what matters: vulnerabilities via OSV, licenses via SPDX, provenance — by hand first, then through interfaces, with honest findings.</description><content:encoded>&lt;![CDATA[<p>Second of two articles about software bills of materials. The inventory is in
place — what it can answer, and what it cannot: vulnerabilities, licenses, and
provenance, first by hand and then through APIs.</p><h2 id="where-part-1-left-off">Where Part 1 Left Off</h2><p>At the end of the first part, a document is on the table with three properties
that cannot be taken for granted.</p><p>It is<strong>complete enough</strong>: 218 components from two generators, because a Maven
tool does not see the npm side of a Vaadin application, and vice versa. It is<strong>reproducible</strong>: two builds from a fresh checkout deliver the same numbers,
ever since a lockfile went under version control. And it sits<strong>next to the
artifact</strong>, not in the build directory — in both delivery formats, for just
under 0.3 percent of the transfer size.</p><p>If you have not read Part 1, you lose nothing here. It is enough to know: the
document describes what was shipped, and it describes it more precisely than a
document that knows only one half.</p><h3 id="what-can-now-be-answered">What Can Now Be Answered</h3><p>A bill of materials is a list. On its own it answers no question — it makes
questions<em>answerable</em> that previously could not even be asked:</p><ul><li>Does my delivery contain a component with a known vulnerability?</li><li>Does one of the included licenses conflict with the planned distribution?</li><li>Where does the code I ship come from?</li></ul><p>All three come up not on the day of the build but weeks later — and then under
time pressure.</p><h3 id="what-the-document-alone-does-not-deliver">What the Document Alone Does Not Deliver</h3><p>The list names names and versions. Whether an advisory exists for one of those
versions is not in it, and it<em>cannot</em> be in it: advisories come into being
later than the document. A bill of materials from May knows nothing about a
vulnerability from August.</p><p>From this follows the structure of this article. Chapter 2 answers the first
question<strong>without any tooling</strong> — just the document and a public database.
Only Chapter 3 shows what a platform delivers beyond that, and only then can
you judge whether the difference is worth it.</p><p>The other way around, it would be a product demo.</p><h2 id="am-i-affected--without-a-service">Am I Affected? — Without a Service</h2><p>The question can be answered with on-board means. Two things are needed: the
document and a public vulnerability database that understands package
identifiers.</p><p>The identifier is the key. Every component in the document carries a<strong><a href="https://8g8.eu/dj9xf1">purl</a></strong> — a string that unambiguously combines ecosystem, name, and
version:</p><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">code</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><pre tabindex="0"><code>pkg:maven/org.jsoup/jsoup@1.23.1?type=jar
pkg:npm/%40vaadin/react-components@25.2.7</code></pre></div><p>This makes the query a translation task, not analysis work. The identifiers
are read from the document and held against the database:</p><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">python</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">purls</span><span class="o">=</span><span class="p">[</span><span class="n">c</span><span class="p">[</span><span class="s2">"purl"</span><span class="p">]</span><span class="k">for</span><span class="n">c</span><span class="ow">in</span><span class="n">sbom</span><span class="p">[</span><span class="s2">"components"</span><span class="p">]</span><span class="k">if</span><span class="n">c</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"purl"</span><span class="p">)]</span></span></span><span class="line"><span class="cl"><span class="n">abfrage</span><span class="o">=</span><span class="p">{</span><span class="s2">"queries"</span><span class="p">:</span><span class="p">[{</span><span class="s2">"package"</span><span class="p">:</span><span class="p">{</span><span class="s2">"purl"</span><span class="p">:</span><span class="n">p</span><span class="p">}}</span><span class="k">for</span><span class="n">p</span><span class="ow">in</span><span class="n">purls</span><span class="p">]}</span></span></span><span class="line"><span class="cl"><span class="c1"># POST https://api.osv.dev/v1/querybatch</span></span></span></code></pre></div></div><p>For the inventory examined here:<strong>217 identifiers, not a single advisory.</strong>
The result matches what the platform says later — so the basic answer costs
nothing but a few lines.</p><h3 id="the-cross-check">The Cross-Check</h3><p>A result with no hits proves little as long as you do not know whether the
query<em>would</em> deliver hits at all. Until recently, the same application
carried an older version of one library:</p><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">code</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><pre tabindex="0"><code>1.22.1: 1 Meldung GHSA-pmhh-3w7g-xqp8 MODERATE behoben in 1.23.1
"Cleaner may expose markup with custom raw-text elements"
1.23.1: 0 Meldungen</code></pre></div><p>The query works, the inventory is clean, and the difference between the two
versions is a single digit. This is exactly why the bill of materials was
collected.</p><h3 id="where-it-ends">Where It Ends</h3><p>What is missing here is not a detail — it is everything that turns information
into a decision:</p><ul><li><strong>No urgency rating.</strong> That an advisory exists says nothing about how likely
it is to be exploited.</li><li><strong>No indication of known exploitation.</strong> Whether a vulnerability is actually
being attacked is recorded in a different catalog.</li><li><strong>No history.</strong> The query describes today. Whether the same component was
already affected three releases ago remains open.</li><li><strong>No comparison across multiple deliveries.</strong> Anyone operating twenty
applications repeats the same script twenty times.</li></ul><p>The last point is where the manual approach tips over. For a single
application, the query is a quick exercise. For an inventory that grows over
years, it is a task with its own maintenance cost — and that is where the
question begins of what a tool can take off your hands.</p><h2 id="vulnerabilities-with-a-platform">Vulnerabilities with a Platform</h2><p>The same inventory, this time uploaded instead of queried. What a platform
delivers on top is best shown with the version that still carried the finding
— both sit there side by side.</p><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">code</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><pre tabindex="0"><code>GHSA-pmhh-3w7g-xqp8 jsoup 1.22.1 MEDIUM CVSS 4.7
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
EPSS 0,0019 (Perzentil 8,8) bekannt ausgenutzt: nein behoben in 1.23.1
"Cleaner may expose markup with custom raw-text elements"</code></pre></div><p>Four of these data points were not available in Chapter 2: the vector, the
probability score, the indication of known exploitation, and the fixing
version. The third value in particular changes the urgency — an advisory with
a percentile of 8.8 is something different from one that is under active
attack.</p><h3 id="the-before-and-after-comparison">The Before-and-After Comparison</h3><table><thead><tr><th/><th>Version with legacy components</th><th>Version with lockfile</th></tr></thead><tbody><tr><td>Components</td><td>248</td><td>218</td></tr><tr><td>Advisories</td><td><strong>1</strong> (MEDIUM)</td><td><strong>0</strong></td></tr></tbody></table><p>The second row is not the platform&rsquo;s achievement but maintenance&rsquo;s: the
library was lifted to the fixing version. The platform&rsquo;s part in it is a
different one — it keeps both states side by side, so the path from one row to
the other remains traceable. That is exactly what a single query does not
deliver.</p><h3 id="the-honest-finding">The Honest Finding</h3><p>The finding sat in the<strong>Maven half</strong> of the document. The npm half, which
Part 1 added with some effort, was and is free of advisories.</p><p>That is inconvenient because it contradicts the obvious narrative: the merge
from Part 1 uncovered<strong>no</strong> finding here that a Maven-only SBOM would have
hidden. Anyone advocating the merge should not claim it brought a lucky find
to light.</p><div class="pull-quote"><p>The case for merging rests on coverage, not on a finding. A half you do not
check is not clean just because you have not checked it.</p></div><p>That the npm side carries no advisory today is a statement about today — and
it is only possible because that side is in the document at all.</p><h3 id="what-the-count-reveals">What the Count Reveals</h3><p>A detail on the side that calls for caution: depending on which access path is
queried, the same platform reports<strong>one</strong> finding for the same inventory in
one place and<strong>two medium and one low</strong> in another. And through one interface
the version appears as 1.22.1, through the other as 1.22.2 — the delivery
directory contains 1.22.2.</p><p>Both have been reported and do not fundamentally call the answers into
question. They are, however, an argument for not adopting a number unchecked
just because a tool delivers it — the same skepticism Part 1 applied to the
self-computed document.</p><h2 id="supply-chain-data-for-agents">Supply Chain Data for Agents</h2><p>Next to the regular API stands a second one that is likely the more
interesting for this readership: an<strong>MCP server</strong>. The Model Context Protocol
is the way a language model calls tools — and supply chain data is an obvious
subject for it, because the questions asked of it are almost always phrased in
natural language.</p><p>Access is stateless, authentication the same as for the regular API.<strong>41
tools</strong> are offered:</p><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">code</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><pre tabindex="0"><code>get_bom_stats get_bom_vulnerabilities get_org_vulnerabilities
get_bom_components get_bom_dependencies check_component_vulnerabilities
get_license_problems_count get_org_restricted_licenses get_ai_license_analysis
get_provenance_results get_org_provenance_countries get_org_supply_risk
get_quality_gate_detail list_audit_logs whoami</code></pre></div><p>This turns &ldquo;Are we affected?&rdquo; into a question that can be asked by someone who
knows neither purl nor query syntax.</p><h3 id="a-finding-on-the-side">A Finding on the Side</h3><p>Comparing the two access paths, something stands out that is unlikely to be
intended:<strong>the MCP server hands out information that the regular API refuses
to the same key.</strong> Who is this key, which organizations exist, what is the
organization-wide vulnerability picture — answered over one protocol,
acknowledged with a rejection over the other.</p><p>This is not a security hole; the data belongs to the owner of the key. But it
shows that two access paths to the same data have two permission checks — and
those can drift apart.</p><h3 id="a-precaution-that-deserves-attention">A Precaution That Deserves Attention</h3><p>Third-party content comes back marked:</p><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">json</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="s2">"description"</span><span class="err">:</span><span class="s2">"&lt;untrusted&gt;jsoup: Cleaner may expose markup</span></span></span><span class="line"><span class="cl"><span class="s2"> with custom raw-text elements&lt;/untrusted&gt;"</span><span class="err">,</span></span></span><span class="line"><span class="cl"><span class="s2">"component"</span><span class="err">:</span><span class="s2">"&lt;untrusted&gt;jsoup&lt;/untrusted&gt;"</span></span></span></code></pre></div></div><p>The reason is immediately convincing once you have seen it. The description of
a vulnerability is text someone else wrote. Presented to a language model, it
is input from a third party&rsquo;s hand — and could contain instructions instead of
a description.</p><div class="pull-quote"><p>Anyone feeding supply chain data to a language model is feeding it text from
the supply chain. The marker says: this is content, not an instruction.</p></div><p>For an article about supply chain security, that is an elegant twist. The
chain whose trustworthiness is at stake reaches all the way into the
description texts used to examine it.</p><h2 id="licenses-what-the-traffic-light-reports-and-what-it-overlooks">Licenses: What the Traffic Light Reports and What It Overlooks</h2><p>Twelve different licenses are spread across 218 components. The distribution
is unremarkable — and that is exactly why the close look pays off.</p><table><thead><tr><th>License</th><th>Components</th></tr></thead><tbody><tr><td>Apache-2.0</td><td>159</td></tr><tr><td>EPL-2.0</td><td>40</td></tr><tr><td>MIT</td><td>16</td></tr><tr><td>EUPL-1.2</td><td>14</td></tr><tr><td>BSD-3-Clause</td><td>10</td></tr><tr><td>GPL-2.0 with Classpath Exception</td><td>7</td></tr><tr><td>others (LGPL-2.1, CDDL, Bouncy Castle, Apache-1.0 …)</td><td>1 each</td></tr></tbody></table><p>The automated check reports<strong>one</strong> restricted license and no conflict.</p><figure><img src="/images/2026/09/what-an-sbom-reveals-when-you-ask-it-sbom-lizenzen.png" alt="License distribution across 218 components, EPL-2.0 flagged as restricted" loading="lazy" decoding="async"/><p><em>Figure 1: Twelve licenses, one flag — and one that carried no identifier.</em></p><h3 id="what-gets-reported">What Gets Reported</h3><p>Flagged is<strong>EPL-2.0</strong> with 40 components — because of the commercial
contributor&rsquo;s indemnification obligation on commercial distribution. Affected
are, of all things, the servlet container and the storage layer — exactly the
building blocks an application absorbs when it ships the server itself.</p><p>That is a useful report. It calls not for panic but for a decision: anyone who
distributes under these terms should know the obligation.</p><h3 id="what-was-not-reported">What Was Not Reported</h3><p>More interesting is the case the same check<strong>overlooked</strong> in the same
application — visible only because both versions sit side by side. The older
one contained a charting library under a commercial license. Its license
entry did not name an identifier but an address:</p><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">code</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><pre tabindex="0"><code>"license": { "url": "https://www.highcharts.com/license" }</code></pre></div><p>A check that holds identifiers against a list finds nothing here it could
compare — and consequently reports nothing.</p><div class="pull-quote"><p>The check reports the license it understands and passes over the one it does
not. The second is the commercially riskier one.</p></div><h3 id="the-uncomfortable-punch-line">The Uncomfortable Punch Line</h3><p>That this component is no longer in the document today is<strong>no achievement of
the license check</strong>. It disappeared because a lockfile was introduced and the
package tree has since contained only what the project declares — the library
was a leftover nobody had noticed.</p><p>A traffic light that knows only identifiers would have carried it along
indefinitely without once turning yellow. For practice, a simple rule follows:<strong>components without an SPDX identifier are not an edge case — they are the
spot where you have to look yourself.</strong> There are usually few of them; here it
was exactly one.</p><h2 id="where-does-the-code-come-from">Where Does the Code Come From?</h2><p>The third question is the one that remains practically unanswerable without
tooling — and the one that has been asked regularly since the European cyber
resilience legislation.</p><p>It is not &ldquo;who published the library,&rdquo; but:<strong>who contributed to it, and from
where?</strong> The answer is not in the SBOM. It is derived by evaluating the
contribution histories of the source projects.</p><h3 id="the-result-for-this-inventory">The Result for This Inventory</h3><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">code</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><pre tabindex="0"><code>evaluable: 34 of 218 components
United States 2,513 United Kingdom 367
Germany 667 France 309
Unknown 503 Japan 303
China 502 Canada 252
Russia 423 India 235</code></pre></div><figure><img src="/images/2026/09/what-an-sbom-reveals-when-you-ask-it-sbom-herkunft.png" alt="Contributors by country, eleven countries with sanctions relevance flagged" loading="lazy" decoding="async"/><p><em>Figure 2: Eleven of the 89 countries appear on a list — the two largest of them in third and fourth place.</em></p><p>The numbers are contributors, not components. They show a picture most
projects are likely to share: a core shaped by the English-speaking world, a
substantial European share — and, with China and Russia, two countries that
raise questions of their own in a risk assessment.</p><h3 id="why-this-is-an-indication-not-evidence">Why This Is an Indication, Not Evidence</h3><p>Three caveats belong to every one of these numbers, and anyone who omits them
is using the evaluation wrong:</p><p><strong>Coverage is low.</strong> 34 of 218 components could be evaluated — for the rest,
accessible histories are missing. The table says nothing about more than four
fifths of the inventory.</p><p><strong>&ldquo;Unknown&rdquo; is the third-largest group.</strong> 503 contributors without an
attribution rank ahead of everything that follows. Every statement about
shares has this blur built in.</p><p><strong>The attribution itself is an estimate.</strong> It rests on time zones, name forms,
and address fragments — attributes a person can change, and which, across a
distributed project, say nothing about who has the authority to give
instructions.</p><div class="pull-quote"><p>A contributor with an address in some country is no proof that someone there
exerts influence on the software. It is an indication of where taking a
closer look might pay off.</p></div><h3 id="what-it-is-still-good-for">What It Is Still Good For</h3><p>For a discussion about dependence on individual regions, such a distribution
is the only available entry point — by hand, it cannot be compiled for 218
components. It should be used for what it is: a map, not a verdict.</p><p>And as an occasion to ask the other question no tool answers: how many of
these components would you miss if they were no longer maintained as of
tomorrow?</p><h2 id="cryptography-and-provenance-two-evaluations-with-reservations">Cryptography and Provenance: Two Evaluations with Reservations</h2><p>Two evaluations go beyond what the chapters so far have shown. Both answer
questions that remain unanswerable without tooling — and in both cases the
answer is weaker than its numbers suggest.</p><p>A side note on availability, because it contains a more general lesson. Both
evaluations were initially unavailable — the API responded with the
explanation that these endpoints are<strong>fundamentally</strong> closed to access keys.
That sounded like a product decision no key could remedy, and it was planned
for accordingly.</p><p>It was not true. In fact, the key was missing two permissions. With an
extended key, the same endpoints deliver data without complaint, over both
access paths.</p><div class="pull-quote"><p>An error message that says &ldquo;not possible, period&rdquo; where &ldquo;you are missing a
permission&rdquo; would be correct costs the recipient days — they stop looking.</p></div><p>In practice this means: when a rejection sounds like a product boundary,
asking back pays off before you strike the evaluation from the plan.</p><h3 id="cryptography-a-finding-that-reports-uncertainty">Cryptography: A Finding That Reports Uncertainty</h3><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">code</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><pre tabindex="0"><code>Risikowert 12 / 100 Abdeckung 100 %
Krypto-Bausteine 1 Funde 1 (mittel)</code></pre></div><p>The one building block is the<strong>BouncyCastle</strong> library in version 1.84. It was
recognized not because anyone had read its code, but by its name — the rule
amounts to &ldquo;known cryptography library in the inventory.&rdquo;</p><p>What matters is what the finding says. It does not say &ldquo;weak cryptography is
used here.&rdquo; It says:</p><div class="pull-quote"><p>Check whether this cryptographic capability is actually used at runtime, and
record the mapping where it is.</p></div><p>The rationale names three drivers, and the third is the real one:<em>actual
usage at runtime is not declared.</em> Consistently, the finding&rsquo;s category is not
&ldquo;vulnerability&rdquo; but<strong>coverage</strong>, its risk type &ldquo;uncertainty about
cryptographic capabilities.&rdquo;</p><p>This reaches the same limit Part 1 already marked, just one level deeper:<strong>the bill of materials knows the library is there. It does not know which
algorithms run.</strong> Anyone who wants to know that needs a dedicated cryptography
bill of materials with a runtime reference — and no tool writes that on its
own.</p><h3 id="provenance-a-number-that-needs-explaining">Provenance: A Number That Needs Explaining</h3><div class="code-wrap"><div class="code-wrap__bar"><span class="code-wrap__lang">code</span><button type="button" class="code-wrap__copy" aria-label="Copy code">Copy</button></div><pre tabindex="0"><code>Score 43 / 100 (medium)
Components with origin 22 of 38 evaluated
Contributors with origin 427 of 3,601
Countries 11 of 89 on a list
Lists ICTS · ITAR · OFAC</code></pre></div><p>Broken down, the distribution is very uneven:</p><table><thead><tr><th>Country</th><th>Contributors</th><th>Components</th><th>Lists</th></tr></thead><tbody><tr><td>China</td><td>214</td><td>17</td><td>ICTS, ITAR</td></tr><tr><td>Russia</td><td>179</td><td>21</td><td>ICTS, ITAR</td></tr><tr><td>Iran</td><td>15</td><td>11</td><td>ICTS, ITAR, OFAC</td></tr><tr><td>Lebanon, Hong Kong</td><td>4 each</td><td>5 – 6</td><td>ITAR</td></tr><tr><td>Ethiopia, Belarus</td><td>3 each</td><td>5 – 8</td><td>ITAR</td></tr><tr><td>Myanmar, Libya, Venezuela, Haiti</td><td>1 – 2</td><td>2 – 5</td><td>ITAR</td></tr></tbody></table><p>Iran leads the rating because the country appears on all three lists — with
fifteen contributors out of a total of 3,601.</p><h3 id="why-22-of-38-does-not-mean-what-it-seems-to-mean">Why 22 of 38 Does Not Mean What It Seems to Mean</h3><p>A component counts as affected as soon as<strong>a single</strong> contributor from a
listed country has worked on it. For projects with hundreds of contributors
over two decades, that point is reached quickly. That more than half of the
evaluable components are flagged this way therefore says something about the
nature of open-source development first — and about risk only second.</p><p>On top of that come the caveats from Chapter 6, here with greater weight: 38
of 218 components are evaluable at all, the mean attribution confidence is
0.68, and the attribution rests on attributes a person can change.</p><div class="pull-quote"><p>Sanctions lists govern business relationships, not the origin of
contributions. A contribution from a listed country is not a legal
violation, and this evaluation is not a legal review.</p></div><p>What it delivers is a map: anyone who has to write a risk assessment for a
government agency or a major customer has an entry point here that they could
not compile by hand for 218 components. Anyone who reads it as a verdict makes
wrong decisions about people.</p><h3 id="where-a-platform-pays-off--and-where-it-does-not">Where a Platform Pays Off — and Where It Does Not</h3><p>At this point, the question Chapter 2 raised can be answered. The basic answer
— am I affected? — costs a few lines and no service. What cannot be built
in-house is this: a maintained mapping from packages to contribution
histories, a continuously updated assessment basis, and the running record
across many deliveries.</p><p>Anyone who wants to know once whether an advisory affects them does not need
this. Anyone who has to prove for years what they shipped will either buy it
or build it themselves — and the in-house build is more expensive than it
looks.</p><h2 id="obligations-formats-recommendation">Obligations, Formats, Recommendation</h2><p>Up to this point, the bill of materials has been a good idea. For a growing
share of manufacturers it becomes a requirement — the European legal act on
cyber resilience demands, among other things, that for products with digital
elements the manufacturer knows and documents the included components.</p><p>Two points on this, without any claim to be legal advice: the reporting
obligations for actively exploited vulnerabilities have applied since
September 2026; the remaining requirements follow at the end of 2027. And it
is not only those who sell software who are affected — anyone who makes it
available in the course of a commercial activity falls under it as well.</p><p>Anyone who starts now has the advantage of being able to do it properly
without deadline pressure.</p><h3 id="the-four-formats-four-axes">The Four Formats, Four Axes</h3><table><thead><tr><th>Format</th><th>Completeness</th><th>Verifiability</th><th>Queryability</th><th>Effort</th></tr></thead><tbody><tr><td>WAR on an installed server</td><td>low — the server is missing</td><td>partial</td><td>same</td><td>low</td></tr><tr><td>Thin Distribution</td><td>high</td><td><strong>complete</strong></td><td>same</td><td>low</td></tr><tr><td>Fat JAR</td><td>high</td><td><strong>none</strong></td><td>same</td><td>low</td></tr><tr><td>jlink distribution</td><td>high, without the runtime</td><td>like Thin</td><td>same</td><td>medium</td></tr></tbody></table><p>The third column is the same everywhere, and that is not a flaw in the table:<strong>queryability does not depend on the packaging.</strong> It depends on whether the
document is complete and whether anyone asks it questions. Both are
independent of whether an archive or a directory tree ships in the end.</p><p>Anyone who has the choice and needs auditability takes the Thin Distribution —
it is the only format in which every line of the document can be held against
a file in the release.</p><h3 id="the-objection-that-belongs-here">The Objection That Belongs Here</h3><p>The article series these measurements come from pursues one direction: with
every step, more responsibility moves from the server into the release. Less
installed software, fewer assumptions about the environment, less dependence
on others.</p><p>Handing an SBOM to a service runs counter to this direction. The objection is
legitimate and deserves an answer rather than a shrug.</p><h3 id="the-resolution">The Resolution</h3><p>It lies in the order in which this article is built.</p><p><strong>The document lives in the release.</strong> It is usable without any service —
Chapter 2 showed that the basic answer costs a few lines and delivers the same
result.</p><p><strong>The platform answers the questions that go beyond a single release:</strong>
comparisons across versions, ratings by exploitability, license checking
across the entire inventory, provenance estimation. Anyone who does not need
them loses nothing.</p><div class="pull-quote"><p>The inventory belongs to whoever ships. A service is an ingredient, not a
prerequisite. Whoever turns that around has bought a new dependency in order
to document an old one.</p></div><h3 id="what-remains">What Remains</h3><p>Three sentences from two articles:</p><p><strong>The SBOM describes the dependency graph, not the delivery.</strong></p><p><strong>An SBOM covers what its generator can see.</strong></p><p><strong>A bill of materials that cannot be reproduced proves nothing.</strong></p><p>All three are inconvenient, and all three were measured on a single
application you can rebuild yourself in half an hour. That is the real
recommendation: do not believe the bill of materials — hold it against your
own artifact once. The surprises come on their own.</p>
]]></content:encoded><category>Java</category><category>Security</category><media:content url="https://svenruppert.com/images/2026/09/what-an-sbom-reveals-when-you-ask-it-hero.png" medium="image"/><media:thumbnail url="https://svenruppert.com/images/2026/09/what-an-sbom-reveals-when-you-ask-it-hero.png"/><enclosure url="https://svenruppert.com/images/2026/09/what-an-sbom-reveals-when-you-ask-it-hero.png" type="image/jpeg" length="0"/></item></channel></rss>