Experimental SBOM viewer application https://d3pvyjb5xucdu8.cloudfront.net/
  • TypeScript 43.6%
  • Svelte 34.5%
  • HCL 18.1%
  • CSS 2.6%
  • JavaScript 0.9%
  • Other 0.3%
Find a file
Liam Davison 98c107e800
All checks were successful
Deploy / deploy (push) Successful in 1m26s
Merge pull request 'Warn when a BOM contains no vulnerabilities' (#6) from no-vulnerabilities into main
Reviewed-on: #6
2026-07-30 20:14:00 +01:00
.forgejo/workflows Serve the site over HTTPS from CloudFront 2026-07-28 06:32:07 +01:00
.vscode Scaffold CycloneDX SBOM viewer SPA 2026-07-27 16:25:39 +01:00
infra Serve the site over HTTPS from CloudFront 2026-07-28 06:32:07 +01:00
samples Accept CycloneDX 1.7 and add a Trivy sample with findings 2026-07-27 16:48:21 +01:00
src Warn when a BOM contains no vulnerabilities 2026-07-30 20:11:43 +01:00
static Scaffold CycloneDX SBOM viewer SPA 2026-07-27 16:25:39 +01:00
.gitignore Add a script to scan this project's own dependencies 2026-07-27 21:48:14 +01:00
.npmrc Scaffold CycloneDX SBOM viewer SPA 2026-07-27 16:25:39 +01:00
.prettierignore Keep tooling out of pnpm's store when CI puts it in the workspace 2026-07-27 20:59:28 +01:00
.prettierrc Scaffold CycloneDX SBOM viewer SPA 2026-07-27 16:25:39 +01:00
CLAUDE.md Serve the site over HTTPS from CloudFront 2026-07-28 06:32:07 +01:00
eslint.config.js Keep tooling out of pnpm's store when CI puts it in the workspace 2026-07-27 20:59:28 +01:00
package.json Add a script to scan this project's own dependencies 2026-07-27 21:48:14 +01:00
pnpm-lock.yaml Scaffold CycloneDX SBOM viewer SPA 2026-07-27 16:25:39 +01:00
pnpm-workspace.yaml Scaffold CycloneDX SBOM viewer SPA 2026-07-27 16:25:39 +01:00
README.md Serve the site over HTTPS from CloudFront 2026-07-28 06:32:07 +01:00
tsconfig.json Scaffold CycloneDX SBOM viewer SPA 2026-07-27 16:25:39 +01:00
vite.config.ts Serve the site over HTTPS from CloudFront 2026-07-28 06:32:07 +01:00

SBOM Viewer

A single-page app for inspecting CycloneDX SBOM files. The user picks a .json BOM and the browser parses it, showing a list ordered worst-first — components, or every finding at once — with a detail pane for whichever is selected. Findings link to the components they affect and back.

There is no backend, no authentication and no persistence — the BOM never leaves the browser, and reloading the page discards it. The built output is static files served from a private S3 bucket through CloudFront.

Status

Working and deployed. https://d3pvyjb5xucdu8.cloudfront.net

Area State
App Complete — parsing, component and findings views, the SBOM Explorer design
Infrastructure Applied — private S3 bucket behind CloudFront, HTTPS, deploy IAM user (infra/)
Deployment Live, last published by hand with aws s3 sync
CI Workflow written (.forgejo/workflows/deploy.yml), not yet green end to end

Known gaps:

  • Runner caching is not enabled. pnpm's store lands inside the workspace on the Forgejo runner — its default store directory is on a different filesystem from the bind-mounted workspace, and pnpm cannot hardlink across devices — so it is discarded with the workspace and every build re-downloads all dependencies. Fixing it means either an actions/cache step keyed on pnpm-lock.yaml, or a persistent Docker volume in the runner's valid_volumes with pnpm config set store-dir pointing at it. Nothing is broken by this; builds are just slower than they need to be.
  • The deploy workflow triggers on main, so nothing publishes until the feature branches merge down.
  • The published site predates the CloudFront switch. The infrastructure is applied, but the objects in the bucket are from the last hand-deploy, so the live HTML carries neither the hash-based <meta> CSP nor the #app class that replaced its inline style attribute. Nothing is visibly broken, but inline script is protected only by the header's 'unsafe-inline' until the next deploy.
  • The old http://sbom-findings-viewer.s3-website.eu-west-2.amazonaws.com URL is dead — website hosting is off and the bucket is private. Anything pointing at it needs updating.
  • Every URL answers 200 with the app's HTML, including genuine 404s — that is what the SPA fallback does. Crawlers and uptime checks read those URLs as present. It only matters if client-side routes are added; there is one page today.
  • Access logging is not enabled on the distribution. It needs a log bucket and a retention decision, neither of which exists yet.

Getting started

pnpm install
pnpm dev

Three sample BOMs are checked in:

  • samples/example-bom.json — small, and deliberately awkward: nested components, multiple ratings on one finding, severity aliases, an unresolvable affects reference. Use it to exercise the parser's normalization and the warning banner.
  • samples/trivy.sbom.json — 395 KB, 482 components and 17 real findings across all four severities, from Trivy. The one to use when working on anything vulnerability-related.
  • samples/codereview-bom.json — 1.3 MB, 741 components, produced by cyclonedx-npm. Use it to check rendering at realistic scale. It carries no vulnerability data, as cyclonedx-npm inventories dependencies without scanning them.

Scripts

Command Purpose
pnpm dev Dev server with HMR
pnpm build Static production build into build/
pnpm preview Serve build/ locally
pnpm test Unit tests (Vitest)
pnpm check Svelte + TypeScript type check
pnpm lint Prettier check and ESLint
pnpm format Rewrite files with Prettier

Stack

SvelteKit 2 with Svelte 5 (runes), Tailwind CSS 4, TypeScript, adapter-static.

Deployment

pnpm build emits a fully static site to build/, with index.html doubling as the SPA fallback. It is synced to a private S3 bucket and served by CloudFront, which terminates TLS, adds the security headers (HSTS, CSP and the rest), and turns unknown paths back into index.html — the counterpart of adapter-static's fallback option.

Infrastructure lives in infra/ as OpenTofu and is applied by hand. .forgejo/workflows/deploy.yml publishes the site on pushes to main; the same sync can be run manually with the commands in the infra README.