Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@peachstudio/synapse-sbom) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@peachstudio/synapse-sbom
Command:
synapse-sbom· npm package:@peachstudio/synapse-sbom
Generate a CycloneDX 1.6 SBOM from your npm project locally and submit it to SYNAPSE Software Component Analysis (SCA). Vulnerable components are then continuously re-evaluated as new advisories land — scan once, monitored forever.
- Zero runtime dependencies. Node ≥ 18.
- The SBOM is built on your machine; only the SBOM JSON leaves it.
- Re-scans update the same product (stable project identity), so history and continuous monitoring survive renames and CI re-runs.
Quick start
# 1. Create an API key in the SYNAPSE webapp (see "Authentication" below):
# Settings → Security → API Keys → name it → Create → copy the syn_… key
# 2. Store it once (written to ~/.config/synapse-sbom/config.json, mode 600):
npx @peachstudio/synapse-sbom login --key syn_xxxxxxxxxxxx
# 3. From your project root (needs package.json + package-lock.json):
npx @peachstudio/synapse-sbom scanThat's it. Output:
Project identity: git:github.com/acme/web (git remote)
Generated CycloneDX SBOM: acme-web@2.3.0 (412 components)
Submitting 412 component(s) to https://api.synapse-intel.com …
Done in 7s (HTTP 200)
Submitted to https://api.synapse-intel.com
product : acme-web (d51e5833-…)
components : 412
vulnerable : 5
new CVEs : 2Install it instead of using npx if you prefer (the installed command is
synapse-sbom):
npm i -g @peachstudio/synapse-sbom # global CLI → `synapse-sbom`
npm i -D @peachstudio/synapse-sbom # or as a dev dependency, run via npm scriptsCommand reference
Copy-paste, no install needed (npx). If installed globally, drop the
npx @peachstudio/synapse-sbom prefix and just use synapse-sbom.
# Authenticate once — key stored 0600 at ~/.config/synapse-sbom/config.json
npx @peachstudio/synapse-sbom login --key syn_xxx --url https://api.synapse-intel.com
npx @peachstudio/synapse-sbom login # interactive hidden prompt
# Scan
npx @peachstudio/synapse-sbom scan # current project, submit
npx @peachstudio/synapse-sbom scan ./path/to/app # a specific project
npx @peachstudio/synapse-sbom scan --dry-run # print SBOM only, no upload, no side effects
npx @peachstudio/synapse-sbom scan --product my-svc # override display name
npx @peachstudio/synapse-sbom scan --project my-key # explicit stable project key
# Per-run auth/endpoint overrides (skip stored config)
npx @peachstudio/synapse-sbom scan --url https://api.synapse-intel.com --key syn_xxx
SYNAPSE_API_KEY=syn_xxx SYNAPSE_API_URL=https://api.synapse-intel.com \
npx @peachstudio/synapse-sbom scan
# Local SYNAPSE instead of prod
npx @peachstudio/synapse-sbom scan --url http://localhost:8085 --key syn_local
# Inspect resolved URL / masked key / config path
npx @peachstudio/synapse-sbom whoami
# Help
npx @peachstudio/synapse-sbom help| Flag | Env | Default | Meaning |
|---|---|---|---|
--key |
SYNAPSE_API_KEY |
stored config | Bearer API key |
--url |
SYNAPSE_API_URL |
https://api.synapse-intel.com |
SCA API base URL |
--project |
SYNAPSE_PROJECT |
git remote → generated | Stable project identity (survives renames/CI) |
--product |
— | package.json name |
Display name only |
--dry-run |
— | off | Build SBOM, print to stdout, don't upload or write .synapse-sbom.json |
| — | SYNAPSE_TIMEOUT_MS |
1200000 (20 min) |
Client request timeout |
| — | SYNAPSE_SBOM_CONFIG_DIR |
~/.config/synapse-sbom |
Config directory |
Resolution order (key & URL): flag > env > stored config > default.
Security: the SBOM is built locally; only it (+ a Bearer key over
HTTPS) leaves your machine. The key is never written to the project,
the SBOM, or .synapse-sbom.json. The CLI warns if you point
--url at a plaintext http:// non-local host (cleartext-key risk);
http://localhost and https:// are silent. Exit code 0 on success,
1 on any error (CI-friendly).
Authentication (API key)
Get a key
- Sign in to the SYNAPSE webapp.
- Go to Settings → Security → API Keys. API access requires a Business (up to 5 keys) or Enterprise (up to 20 keys) tier — lower tiers see an upgrade notice and cannot create keys.
- Enter a name (e.g.
ci-sbom) and click Create. - The key (format
syn_+ 32 hex chars) is shown once in a banner — copy it immediately with the copy button. It is not retrievable later; if lost, revoke it and create a new one. Keys can be revoked anytime from the same screen.
Give the key to the scanner
Three ways, highest precedence first (flag → env → stored config):
| Method | How | Best for |
|---|---|---|
| Flag | --key syn_… on login or scan |
one-off / overrides |
| Env | SYNAPSE_API_KEY=syn_… |
CI (use a secret) |
| Stored config | synapse-sbom login --key syn_… → ~/.config/synapse-sbom/config.json (chmod 600) |
local dev machine |
login also stores the API URL. Verify what's resolved at any time:
synapse-sbom whoami
# API URL : https://api.synapse-intel.com
# API key : syn_abc…(36 chars)
# Config : /home/you/.config/synapse-sbom/config.jsonThe key is only ever stored in that 0600 config file (or your env/CI
secret store) — it is never written into your project tree, the SBOM,
or .synapse-sbom.json.
Commands
| Command | What it does |
|---|---|
synapse-sbom login [--key <k>] [--url <u>] |
Store API key (+ URL) to ~/.config/synapse-sbom/config.json (chmod 600). Omit --key for a hidden interactive prompt. |
synapse-sbom scan [path] |
Build a CycloneDX SBOM for path (default .) and submit it. path must contain package.json + package-lock.json. |
synapse-sbom whoami |
Show the resolved API URL, masked key, and config file path. |
synapse-sbom help |
Usage (also shown with no command or --help). |
scan options
| Flag | Env | Default | Meaning |
|---|---|---|---|
--dry-run |
— | off | Print the CycloneDX SBOM to stdout and do not upload. Does not write .synapse-sbom.json. |
--product <name> |
— | package.json name |
Override the product display name only (identity is the project key, see below). |
--project <key> |
SYNAPSE_PROJECT |
resolved (see below) | Explicit stable project key. |
--url <url> |
SYNAPSE_API_URL |
https://api.synapse-intel.com |
SCA API base URL. Use --url http://localhost:8085 for a local SYNAPSE. |
--key <key> |
SYNAPSE_API_KEY |
stored config | API key for this run (overrides stored config). |
Other environment variables
| Var | Purpose |
|---|---|
SYNAPSE_TIMEOUT_MS |
Client-side request timeout (default 1200000 = 20 min). Large projects resolve server-side; raise this only if you hit a timeout. |
SYNAPSE_SBOM_CONFIG_DIR |
Override the config directory (default $XDG_CONFIG_HOME/synapse-sbom or ~/.config/synapse-sbom). |
Resolution order for API key / URL: flag → env → stored config → default.
Project identity (re-scans update the same product)
Every project gets a stable key so re-scanning always updates the same
product — even after a package.json rename, and identically across every
clone and CI runner. Resolution order:
--project <key>/SYNAPSE_PROJECT- committed
.synapse-sbom.json—{ "projectId": "…" } - the git remote URL, normalized (e.g.
git:github.com/acme/web) - otherwise a UUID is generated and written to
.synapse-sbom.json— commit that file so every clone / CI run scans as the same product.
Server-side identity is (your account, project key); the product name is
just a mutable label. Two unrelated repos that happen to share a package name
do not collide. --dry-run reports the resolved key without writing the
file.
What it sends
- Reads
package.json(→ product name/version) andpackage-lock.json(lockfile v2/v3packagesgraph; v1dependenciesfallback) and builds a CycloneDX 1.6 JSON document withpkg:npm/<name>@<version>purls (scoped names encoded per the purl spec). POST {API_URL}/v1/sca/analyzewithAuthorization: Bearer <key>and body{ "format": "cyclonedx", "sbom": { … }, "product": { "project_key": "…" } }.- The server resolves & enriches vulnerabilities (OSV.dev + NVD + KEV + exploit/PoC signals) and persists the product, SBOM snapshot, and report to your private instance. Prints product id + component / vulnerable / new-CVE counts.
Nothing but the generated SBOM JSON is transmitted. The API key is stored
locally with 0600 permissions and is never written into your project tree.
Use in CI
# .github/workflows/sca.yml
name: SBOM SCA
on: [push]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npx @peachstudio/synapse-sbom scan
env:
SYNAPSE_API_KEY: ${{ secrets.SYNAPSE_API_KEY }}Commit .synapse-sbom.json so every CI run reports as the same product. The
exit code is 0 on success, 1 on any error (auth, network, malformed
project, API error) — fail the build on it as you see fit.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
no package-lock.json … run "npm install" first |
The scanner reads the lockfile, not node_modules. Run npm install/npm ci first. |
no API key — run "synapse-sbom login" … |
No key resolved. login, or pass --key / SYNAPSE_API_KEY. |
API 401 |
Key invalid/revoked, or wrong --url (prod key against local, etc.). Check synapse-sbom whoami. |
API 403 |
Your API-key tier doesn't include SCA (Business/Enterprise). |
API 413 |
SBOM exceeds the server component cap — see the SCA API limits. |
timed out after …s |
Very large project still resolving. Re-run later (results cache) or raise SYNAPSE_TIMEOUT_MS. |
Roadmap
synapse-sbom is the first of a family. PyPI (pip) and Go scanners
will follow the same contract — generate a CycloneDX 1.6 SBOM locally, submit
to /v1/sca/analyze. The SCA engine is already ecosystem-agnostic (npm /
PyPI / Go via purl), so a CycloneDX file from any tool works today.