Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# IcebergSCA — maintenance notes

CLI for supply chain analysis: walk a project, find manifests and lockfiles, resolve the
dependency graph, check every package against OSV, report it.
CLI for software composition analysis: walk a project, find manifests and lockfiles, resolve
the dependency graph, check every package against OSV, report it.

## Commands

Expand Down Expand Up @@ -126,7 +126,7 @@ project's build to discover its dependencies is itself a supply chain risk.
`MavenResolver._backfill` re-reads `pom.xml` to apply BOM-supplied versions to direct dependencies,
which the synchronous parser cannot do because BOMs live on Central.

**Ranges, SARIF and CycloneDX are hand-written** rather than pulled from packages — a supply chain
**Ranges, SARIF and CycloneDX are hand-written** rather than pulled from packages — a dependency
scanner with a large dependency tree of its own is a poor advertisement. Correctness is held by
schema validation in `tests/test_report_formats.py` against the official schemas in `tests/schemas/`.

Expand Down
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# IcebergSCA

Supply chain analysis for software projects. Point it at a directory; it finds every
dependency manifest and lockfile, builds the direct and transitive dependency set, looks each
package up in [OSV](https://osv.dev), and reports what it finds.
Software composition analysis (SCA) for software projects. Point it at a directory; it finds
every dependency manifest and lockfile, builds the direct and transitive dependency set, looks
each package up in [OSV](https://osv.dev), and reports what it finds.

It inventories the third-party components a project declares; it does not read first-party
source code, and it identifies a package by name and version rather than by what the
downloaded artefact contains.

Documentation: <https://icebergai.github.io/IcebergSCA/>

Expand Down Expand Up @@ -47,8 +51,8 @@ lockfile is present does it fall back to resolving version ranges against the re
those findings are labelled `resolved` rather than `pinned`. Java, which has no lockfile, gets
its graph reconstructed from Maven Central and is marked `~` for approximate.

**It never claims to be clean when it isn't.** This is the design constraint everything else
bends around:
**A clean result is never implied unless it was earned.** Most of the rest of the design
follows from this:

- An empty findings list because the lookup never ran is reported as *"vulnerability lookup did
not run"*, never as *"no vulnerabilities found"*. The JSON carries an explicit
Expand All @@ -60,7 +64,7 @@ bends around:
are declared rather than installed.
- Skipped files, truncated graphs and unresolved constraints are all counted and shown.

**Findings never fail your build.**
**Findings do not change the exit code.**

| Exit code | Meaning |
|---|---|
Expand Down Expand Up @@ -119,10 +123,9 @@ icebergsca/.agents/skills/icebergsca/SKILL.md
```

Agents that glob site-packages for `SKILL.md` will find it automatically after install. It
covers invocation, the JSON schema, exit-code semantics, and — most importantly — the three
fields that must be checked before reporting a project as clean. An empty `findings` array
means "checked and clean", "never checked" or "partially checked", and only the report can say
which.
covers invocation, the JSON schema, exit-code semantics, and the three fields to check before
reporting a project as clean. An empty `findings` array means "checked and clean", "never
checked" or "partially checked", and only the report can say which.

## Caching

Expand Down
14 changes: 12 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,25 @@ build-backend = "hatchling.build"
[project]
name = "icebergsca"
version = "0.1.0"
description = "Supply chain analysis for software projects — lockfile-first dependency scanning against OSV"
description = "Software composition analysis for software projects — lockfile-first dependency scanning against OSV"
readme = "README.md"
requires-python = ">=3.11"
# PEP 639: an SPDX expression plus the files to bundle. A "License ::" classifier
# must not be used alongside this form.
license = "Apache-2.0"
license-files = ["LICENSE", "NOTICE"]
authors = [{ name = "Richard Hope" }]
keywords = ["sca", "supply-chain", "security", "osv", "sbom", "cyclonedx", "vulnerabilities"]
keywords = [
"sca",
"software-composition-analysis",
"dependency-scanning",
"supply-chain",
"security",
"osv",
"sbom",
"cyclonedx",
"vulnerabilities",
]
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Console",
Expand Down
4 changes: 2 additions & 2 deletions src/icebergsca/.agents/skills/icebergsca/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
name: icebergsca
description: IcebergSCA usage and output interpretation. Use when scanning a project for vulnerable dependencies, auditing a supply chain, generating an SBOM, or reading an IcebergSCA report. Covers the JSON schema, exit codes, and the checks required before reporting a project as clean.
description: IcebergSCA usage and output interpretation. Use when scanning a project for vulnerable dependencies, performing software composition analysis, generating an SBOM, or reading an IcebergSCA report. Covers the JSON schema, exit codes, and the checks required before reporting a project as clean.
---

# IcebergSCA

Official IcebergSCA skill for running supply chain scans and reading the results correctly.
Official IcebergSCA skill for running dependency scans and reading the results correctly.

IcebergSCA walks a project, finds every dependency manifest and lockfile, resolves the
dependency graph, checks each package against [OSV](https://osv.dev), and reports findings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Notes on the SARIF we emit:
## Full workflow

```yaml
name: Supply chain
name: Dependency scan

on:
push: { branches: [main] }
Expand Down Expand Up @@ -86,8 +86,8 @@ jobs:
category: icebergsca
```

The scheduled run matters more than it looks: most new findings arrive because an advisory was
published, not because the code changed.
The scheduled run matters: most new findings arrive because an advisory was published, not
because the code changed.

## SBOM artefacts

Expand Down
2 changes: 1 addition & 1 deletion src/icebergsca/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""IcebergSCA — supply chain analysis for software projects."""
"""IcebergSCA — software composition analysis for software projects."""

__version__ = "0.1.0"
2 changes: 1 addition & 1 deletion src/icebergsca/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ExitCode(IntEnum):

app = typer.Typer(
name="icebergsca",
help="Supply chain analysis: find dependencies, check them against OSV.",
help="Software composition analysis: find dependencies, check them against OSV.",
no_args_is_help=True,
add_completion=False,
)
Expand Down
2 changes: 1 addition & 1 deletion src/icebergsca/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def sources(self) -> tuple[SourceLocation, ...]:
class SkippedFile:
"""A file we recognised but did not scan, and why.

Skips are always reported. A supply chain tool that quietly drops a manifest is
Skips are always reported. A scanner that quietly drops a manifest is
indistinguishable from one that found nothing wrong with it.
"""

Expand Down
2 changes: 1 addition & 1 deletion src/icebergsca/report/cyclonedx.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
affected by CVE-2021-44228", which would mean shipping the interesting half of the
report in a separate file.

Written by hand rather than through ``cyclonedx-python-lib``. A supply chain scanner
Written by hand rather than through ``cyclonedx-python-lib``. A dependency scanner
that drags in a large dependency tree of its own is a poor advertisement for itself,
and the document is a few nested dictionaries. Correctness is held by validating the
output against the published schema in the test suite.
Expand Down
4 changes: 2 additions & 2 deletions src/icebergsca/resolve/ranges.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
ecosystem's job is reduced to expanding its own shorthand (``^``, ``~>``, ``[1.0,2.0)``)
into those bounds.

Implemented here rather than pulled in from a semver package: this is a supply chain
tool, and every dependency it takes on is one more thing its own users have to trust.
Implemented here rather than pulled in from a semver package: every dependency this
tool takes on is one more thing its own users have to trust.

Every entry point can return ``None``, meaning "this syntax is beyond us". That is
deliberately distinct from "nothing matched" — the caller marks such dependencies
Expand Down
4 changes: 2 additions & 2 deletions website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Notes:
captures in `../docs/img/`. Regenerate those first, then re-copy.
- Nothing is loaded from a CDN: fonts are self-hosted (`font = false` disables
Google Fonts) and the mermaid fence is configured but deliberately unused,
since the theme lazy-loads mermaid from unpkg. A supply chain scanner's own
site should not quietly take a third-party runtime dependency.
since the theme lazy-loads mermaid from unpkg. The site for a dependency
scanner should not quietly take a third-party runtime dependency.
- `docs/stylesheets/iceberg.css` carries the family design tokens verbatim from
the Iceberg (CTI) sheet. Edit them there first, then copy across.
4 changes: 2 additions & 2 deletions website/docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ always the version documented.
- [`references/ci-integration.md`](https://github.com/IcebergAI/IcebergSCA/blob/main/src/icebergsca/.agents/skills/icebergsca/references/ci-integration.md)
— SARIF, SBOM artefacts, gating and caching

## The part that matters
## Before reporting a project clean

An empty `findings` array means "checked and clean", "never checked" or
"partially checked" — and only the report can say which. The skill exists mostly
Expand Down Expand Up @@ -87,7 +87,7 @@ if not report["findings"]:
- **Escalate `malicious: true`.** An OSV `MAL-` advisory is a package published
to attack its consumers, not a bug. The remediation is removal, not upgrade.

## Keeping it honest
## How the skill is kept current

The skill is tested, not just written: `tests/test_skill.py` guards its
location, frontmatter and links, and asserts that
Expand Down
2 changes: 1 addition & 1 deletion website/docs/assets/icebergsca-horizontal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 2 additions & 3 deletions website/docs/ecosystems.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ icebergsca scan . --ecosystem pypi,npm
reports carry the **OSV** name in `package.ecosystem` and the purl type
inside `package.purl`. Correlate on `purl`.

## Caveats worth knowing
## Caveats

### Go reads `go.mod`, never `go.sum`

Expand All @@ -49,8 +49,7 @@ exclusions. Not modelled: profiles, mirrors, relocation and version ranges.
Affected manifests carry `approximate: true`, and the table marks them `~`.

IcebergSCA never shells out to `mvn`. Running a project's own build in order to
discover its dependencies is itself a supply chain risk, and a scanner is a
strange place to take it.
discover its dependencies is itself a supply chain risk.

Gradle sees only literal declarations — no version catalogues, no computed
versions.
Expand Down
8 changes: 7 additions & 1 deletion website/docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ A scan is five stages: **discover → parse → resolve → scan → report**. E
records what it could not do, and that record survives all the way into the
output.

The analysis is composition analysis: it inventories the third-party components
a project declares and checks each one against known advisories. It does not
read first-party source code, and it identifies a package by name and version
rather than by what the downloaded artefact actually contains — so build
provenance, signatures and typosquats are outside what a report can speak to.

## The five stages

### 1. Discover
Expand Down Expand Up @@ -56,7 +62,7 @@ Every package is looked up in [OSV](https://osv.dev), in two passes.
`querybatch` returns advisory IDs; `GET /v1/vulns/{id}` returns the detail that
makes severity and fix versions possible.

Two behaviours here matter more than they look:
Two behaviours here are worth spelling out:

- **Alias merging is required, not cosmetic.** OSV returns one record per
database, so a single CVE arrives as both a GHSA and a PYSEC record — rendered
Expand Down
Loading
Loading