-
Notifications
You must be signed in to change notification settings - Fork 467
Supply Chain Scanning
The Supply-Chain Scanner detects known-malicious (MAL-) and known-vulnerable (CVE / GHSA) software packages across a target's dependency surface, verdicted fully offline against a local copy of the OSV database. It ships as three layers that share one engine and one graph model, so a repository scan, a live-target harvest, and an on-demand agent lookup all dedup into the same Package and MalPackageFinding nodes.
This page is the operator guide. For the full technical reference (container topology, the DIRTY/CLEAN security split, the artifact schema, and the graph writer internals), read README.SUPPLY_CHAIN.md in the repository.
- The three layers
- The tools
- One-time setup: the offline OSV database
- Layer L1: the Supply Chain Scanner (Other Scans)
- Layer L2: Supply-Chain Recon (pipeline)
- Layer L3: agent tools
- Reading the results: the Supply-Chain SCA table
- Graph model
- Security posture
| Layer | What it is | How you start it | Writes graph nodes? |
|---|---|---|---|
| L1 | Standalone audit of an uploaded SBOM / lockfile or a GitHub repository | Other Scans modal, Red Zone toolbar | Yes: Package, MalPackageFinding, Vulnerability{source:'osv'}
|
| L2 | Black-box harvest of a live target's served packages | Recon pipeline (GROUP 5.5), or a partial-recon run | Yes: same nodes, anchored to BaseURL
|
| L3 | On-demand lookups the AI agent calls mid-engagement |
execute_osv_scanner / execute_guarddog agent tools |
No: returns text to the agent |
A vulnerability id starting with MAL- is a terminal malicious verdict (the package itself is malware, for example a typosquat). CVE- / GHSA- ids are ordinary known-vulnerable findings and are never written as malicious. A GuardDog behavioural hit is always suspicious, never malicious; only an OSV MAL- hit is malicious.
| Tool | Role | Version | Runtime |
|---|---|---|---|
| OSV-Scanner | Verdict engine: is a package MAL- (malicious) or CVE / GHSA (vulnerable)? |
v2.4.0 | Go static binary, offline |
| GuardDog | Behavioural analysis: does the package behave like malware (install hooks, obfuscation, exfil, typosquat)? | v3.0.1 | Python (+ semgrep, YARA) |
| retire.js | Black-box JS library + version harvest (L2 only) | v5.4.3 | Node CLI |
SBOMs are synthesized in-process as CycloneDX 1.5 from whatever packages a layer harvested; RedAmon does not run syft, trivy, or cdxgen. The OSV verdict path makes zero network calls. GuardDog and retire.js need registry / signature-file egress and run inside a hardened, isolated analyzer container.
The verdict path reads a local copy of the OSV database from the shared Docker volume redamon-osv-db. It is not downloaded at install time (the container images are eager, the data is lazy). Populate it once per ecosystem:
./redamon.sh supply-chain-sync npm # ~208 MB, first run only
./redamon.sh supply-chain-sync npm PyPI Go # add more ecosystemsSupported ecosystems: npm, PyPI, Go, Maven, crates.io, Packagist, RubyGems, NuGet.
Automatic refresh. OSV publishes new
MAL-/CVEadvisories daily. Once an ecosystem has been synced, the orchestrator refreshes it lazily on the scan-spawn path, TTL-guarded (default 24h). A cold database (never synced) is not bootstrapped on the scan path, because the first download is large and the feature is off by default. Runsupply-chain-syncyourself the first time. A refresh failure (offline host) never blocks a scan; it proceeds against the existing database.
The refresh behaviour is controlled by four orchestrator environment variables, all wired in docker-compose.yml:
| Knob | Default | Meaning |
|---|---|---|
OSV_DB_AUTO_REFRESH |
true |
Set false for a strictly air-gapped deploy (manual sync only) |
OSV_DB_ECOSYSTEMS |
npm (auto-refresh set) |
Ecosystems kept fresh automatically |
OSV_DB_TTL_SECONDS |
86400 |
Freshness window (24h) |
OSV_DB_REFRESH_TIMEOUT |
900 |
Ceiling so a slow download cannot stall a scan spawn |
L1 is a standalone scan you launch from the Red Zone. It audits a dependency manifest you provide, with no live target required.

Step by step:
- Open a project's graph (Red Zone). In the toolbar, click Other Scans.
- Scroll to the full-width Supply Chain Scanner card (below GitHub Secret Hunt and TruffleHog).
- Pick an input source with the toggle:
- Uploaded SBOM / lockfile (default),
- GitHub repository, or
- GitHub organization (scans every repository in an org — see below).
- Provide the input for the selected source (details below).
- Click Start. The logs drawer opens and streams the scan live. Use Pause / Resume / Stop as needed.
- When the scan completes, the
Package/MalPackageFinding/Vulnerabilitynodes are merged into the live graph, and Download yields the raw result JSON.
Click Upload file and choose a manifest. Accepted types: CycloneDX / SPDX SBOMs and lockfiles, extensions .json, .xml, .txt, .lock, .toml, .mod, .sum, .yaml, .yml (for example package-lock.json, yarn.lock, poetry.lock, go.sum, Gemfile.lock, bom.cdx.json). Max 10 MB. One file per project: a new upload replaces the current one. No API key is required for an upload.
File naming matters. OSV-Scanner picks its parser from the file basename, so keep the recognized lockfile / SBOM name (for example
package-lock.json, notdeps.json).
Enter a repository as owner/repo or https://github.com/owner/repo, and optionally a branch or tag. The repository is cloned shallowly inside the scan sandbox and its lockfiles are audited; the checkout is discarded afterwards.
- Public repositories clone anonymously (no token needed).
- Private repositories use the GitHub Access Token from Global Settings > API Keys (the same token shared with GitHub Secret Hunt and TruffleHog).
An L1 GitHub-repo scan anchors its packages to a GithubRepository node; an uploaded SBOM anchors to an SbomDocument node. Both anchors hang off the project's Domain when one exists, so the scan is part of the graph rather than a detached island.
Auditing an organization one repository at a time does not scale, so this mode does it in bulk. Enter a GitHub organization or user name (letters, digits and dashes, 39 characters max) and click Queue org batch.
RedAmon enumerates the account's repositories server-side and queues one supply-chain scan per repository, which then run one after another as capacity frees up. Follow their progress in the Scans tab → Scan queue (see Scan Timeline); each finished repo also lands in Run history as a Supply chain (repo) row.
- This is a batch, not a single scan. The card's Start button is deliberately disabled while this mode is selected: Start runs the project's one configured input, whereas this queues many scans.
- Selecting this mode does not change the project's saved input source, so switching back to Upload or Repository finds your previous input intact.
- Which repositories are included is governed by the project's saved supply-chain org options: include forks, include archived, max repos, and deep analysis.
- Public organizations enumerate anonymously. Private ones need the GitHub Access Token from Global Settings > API Keys. A token that exists but lacks access is reported as an error rather than silently falling back to a partial list.
- The queued jobs are ordinary queue entries: cancel any of them from Scan queue before they start.
Each repository is scanned exactly as in GitHub repository mode (shallow clone in the sandbox, lockfiles audited, checkout discarded), so every repo gets its own GithubRepository anchor in the graph.
Against a live target with no manifest, L2 harvests the npm package set the target actually serves, verdicts it offline, and merges the same node types, anchored to the target's BaseURL nodes. It runs as GROUP 5.5 of the recon pipeline, immediately after JS Recon (whose downloaded JS and detected technologies it consumes), and is also runnable on its own as a partial-recon tool.
The harvest is pure parsing of data JS Recon already downloaded; it makes no new network request. Sources:
-
Source-map mining extracts
node_modules/<pkg>names from source maps (exact names, usually no version). -
Import mining collects bare specifiers from
import/require. -
Technology to purl maps
http_probetechnologies (for exampleReact:18.2.0) to versioned npm purls. - retire.js (inside the hardened analyzer) reads a library name and version straight out of the served JavaScript, so it can verdict libraries the technology table misses.
Names harvested without a version are recorded as Package inventory but cannot be OSV-verdicted (OSV needs a version to match a version-specific advisory); they surface in the SCA table as unverdictable.
Configure it in the project form's JS Recon tab, under Supply Chain Recon:
| Setting | Field | Default | Meaning |
|---|---|---|---|
| Enable | supplyChainReconEnabled |
Off | Runs GROUP 5.5 during a full scan |
| Ecosystems | supplyChainReconEcosystems |
npm |
Which ecosystems to verdict |
| Deep analysis | supplyChainReconDeepAnalysisEnabled |
Off | Runs GuardDog behavioural analysis on OSV-flagged packages (opt-in) |
You can also run just this module with Run partial recon on the section (tool id SupplyChainRecon), which fetches the served JS from the graph's BaseURL / Endpoint URLs (plus any you supply) and runs the harvest, verdict, and graph write standalone.
GuardDog deep analysis is opt-in and flagged-package-only. After the offline OSV pass, it takes the packages OSV already flagged (capped, malicious first) and runs
guarddog <eco> scaninside the hardened analyzer image. Results becomesuspiciousfindings that attach to the existingPackagenode. A download failure becomes asoft_errorfinding (rendered as not analysed), never a silent clean.
Two MCP tools the AI agent calls mid-engagement, exposed on the network_recon server inside the kali-sandbox. Neither writes graph nodes; each returns a compact text summary the agent reasons over. See the full entries in the AI Agent Guide.
-
execute_osv_scanneris passive and fully offline. It accepts a purl (for examplepkg:npm/lodash@4.17.21, synthesized into a one-component SBOM), a workspace lockfile path, or an SBOM path, and returns the OSV verdict.MAL-is a terminal malicious verdict;CVE-/GHSA-are known-vulnerable. Available in all phases. -
execute_guarddogruns GuardDog behavioural analysis of one named package (<ecosystem> <name> [version]). It is DANGEROUS (it downloads the attacker-authored tarball), so it dispatches to the hardened analyzer container rather than unpacking anything in the sandbox. A hit issuspicious, never a terminal verdict. Restricted to the informational and exploitation phases.
Every layer writes into the graph; the Supply-Chain SCA table is where you read it. Open it from the Data Table tab's dropdown (PackageSearch icon, flagged NEW). It is the only view that joins the three node types, and it has three sheets:
| Sheet | One row per | Answers |
|---|---|---|
| Verdicts | MalPackageFinding |
What is on fire right now |
| Packages |
Package, with rolled-up counts |
What am I running, and how much of it was actually checked |
| Advisories | Vulnerability{source:'osv'} |
The CVE / GHSA half |
Three things the table derives rather than reads:
-
Verdict is three-state:
malicious/suspicious/not analysed. A finding withsoft_erroris a package GuardDog never verdicted, rendered as unchecked rather than as a low-severity suspicious hit. -
unverdictableis a first-class package status and a headline count. A short verdict list next to a largeunversionedcount means "mostly unchecked", not "mostly clean". -
Origin (
L1 repo/L1 SBOM/L2 live) is inferred from the anchor node.
Each sheet is deep-linkable (/graph?table=supplyChainSca&sheet=advisories) and exports per sheet to XLSX / JSON / MD. The table is empty until an L1 scan has run from Other Scans or a recon scan has run with Supply-Chain Recon enabled, and it needs the offline OSV database populated first (./redamon.sh supply-chain-sync npm). See the Red Zone table reference.
Two node types are shared by all layers, so a repo scan, an SBOM upload, and a live harvest of the same project dedup onto the same nodes. See the full schema on Attack Surface Graph.
flowchart LR
DOM[Domain]
GR[GithubRepository - L1 repo]
SB[SbomDocument - L1 upload]
BU[BaseURL - L2 live]
PK[Package]
MF[MalPackageFinding]
VU[Vulnerability source=osv]
DOM -->|HAS_REPOSITORY| GR
DOM -->|HAS_SBOM_DOCUMENT| SB
GR -->|DEPENDS_ON| PK
SB -->|DEPENDS_ON| PK
BU -->|DEPENDS_ON| PK
PK -->|FLAGGED_AS| MF
PK -->|HAS_VULNERABILITY| VU
-
Packageis a discovered dependency (purl,ecosystem,name,version,source,source_path). Merge key(purl, user_id, project_id). -
MalPackageFindingis a verdict about a package (verdict=malicious/suspicious,source_tool=osv/guarddog,advisory_id,severity,soft_error,aliases). Merge key(finding_id, user_id, project_id). - All writes MERGE (idempotent), every key is tenant-scoped, and only OSV
MAL-ids becomeverdict=malicious.
The feature separates the code that touches untrusted bytes from the code that holds secrets. Package tarballs, target-served JS, and registry metadata are all attacker-influenceable; the Neo4j password and the GitHub token are not.
-
DIRTY zone (the analyzer container):
cap_drop=ALL, read-only rootfs + tmpfs, non-root, memory / pids / cpu caps, no secrets, on an isolated network. It runs GuardDog and retire.js and emits only a schema-validated JSON artifact. - CLEAN zone (the L1 scan writer and the recon container): holds the Neo4j credentials, validates the artifact (charset + caps + shape) before it crosses the boundary, and writes the graph.
- Offline by default: the OSV verdict path makes zero network calls. GuardDog's registry egress is opt-in and fails closed.
-
NO-INSTALL invariant: RedAmon never runs
npm/pip installon a target manifest (lifecycle scripts are RCE); it parses statically only.
For the container topology, the broker allowlist, and the full artifact schema, see README.SUPPLY_CHAIN.md.
Getting Started
- Getting Started
- Deploying to a Server
- User Management & Roles
- Creating a Project
- Recon Presets
- Global Settings
Core Workflow
- Red Zone
- Recon Pipeline Workflow
- Running Reconnaissance
- Scan Timeline
- AI Agent Guide
- Fireteam — Parallel Specialists
- Exploit-Path Search (LATS)
- Agent Workspace
- Reverse Shells
Scanning & OSINT
- Adversarial AI Recon
- AI Gauntlet
- JS Reconnaissance
- GraphQL Security Testing
- Subdomain Takeover Detection
- VHost & SNI Enumeration
- Web Cache Poisoning
- GVM Vulnerability Scanning
- GitHub Secret Hunting
- TruffleHog Secret Scanning
- Supply-Chain Scanning
AI & Automation
- AI Model Providers
- MCP Tool Plugins
- Knowledge Base & Web Search
- Agent Skills
- Chat Skills
- Tradecraft Lookup
- Playwright Browser Automation
- CypherFix — Automated Remediation
- Rules of Engagement (RoE)
HackLab
Analysis & Reporting
- Insights Dashboard
- TrafficMind
- Pentest Reports
- Attack Surface Graph
- Surface Shaper
- EvoGraph — Attack Chain Evolution
- Data Export & Import
Contributing
Reference & Help