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
74 changes: 74 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Project guidance for Claude

## Pre-push checklist

CI (`.github/workflows/pr-check.yml`) runs four gates and **fails the PR if any
gate fails**. Run all four locally before pushing — `deno task check` and
`deno task test` alone are not sufficient.

```bash
deno fmt --check # CI gate 1 — formatting
deno lint # CI gate 2 — lint
deno check main.ts # CI gate 3 — type check
deno test --allow-net # CI gate 4 — tests
```

Or as a single command:

```bash
deno fmt --check && deno lint && deno check main.ts && deno test --allow-net
```

### Formatting (the most common failure)

`deno fmt --check` is strict about line breaks in import statements, type
unions, and ternaries. The Deno formatter has opinions that don't always match
what an LLM will produce on the first try. **Always** run `deno task fmt` (which
auto-fixes) after writing or editing TypeScript or Markdown files, then verify
with `deno fmt --check`.

If CI fails on formatting after a push, the fix is:

```bash
deno task fmt
git add -u && git commit -m "Apply deno fmt formatting"
git push
```

## Project conventions

- **Runtime**: Deno v2.x. No Node.js or npm install — dependencies are declared
in `deno.json` `imports` and resolved via JSR/npm specifiers.
- **No emojis** in code, comments, or commits unless explicitly requested.
- **Commit style**: plain imperative ("Add X", "Fix Y") — not conventional
commits. Subject under 72 chars, explain _why_ in the body when not obvious.
- **No `Co-Authored-By` trailer** on commits unless explicitly requested.

## Architecture cheat sheet

- `main.ts` — entry point; registers all MCP tools on stdio transport
- `src/registries/` — one client per package registry (npm, maven, pypi, etc.)
- `src/parsers/` — one parser per dependency file format
- `src/tools/` — MCP tool implementations
- `src/utils/` — shared utilities (cache, http, version parsing, vulnerability)
- `src/config/` — custom registry/auth configuration loader

When adding a new registry, you typically need: a registry client
(`src/registries/X.ts`), a parser if it has a dependency file format
(`src/parsers/X.ts`), and registration in `src/registries/index.ts` and
`src/parsers/index.ts`. Update the tool input enums in `src/tools/*.ts` and the
registry list in `README.md`.

## Vulnerability checking

Two databases are queried in parallel and merged by CVE ID:

- **OSV** (`api.osv.dev`) — package-native, broad ecosystem coverage
- **NVD** (`services.nvd.nist.gov`) — authoritative CVSS v3.1 + CWE

Both are cached **per-package** (not per-version) — checking different versions
of the same package reuses the cached API responses. Version filtering happens
client-side via `osvAffectsVersion` and `cveAffectsVersion`. When changing
either, update the tests in `src/utils/vulnerability.test.ts`.

Set `NVD_API_KEY` env var for higher NVD rate limits (50 vs 5 requests/30s).
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ multiple package registries.
JSR, NuGet, Docker Hub, RubyGems, Packagist, pub.dev, Swift PM, GitHub Actions
- **Version lookup**: Get the latest stable (and optionally prerelease) versions
- **Version listing**: List all available versions with metadata
- **Vulnerability scanning**: Check packages against the OSV (Open Source
Vulnerabilities) database
- **Vulnerability scanning**: Check packages against OSV and NVD databases with
deduplicated, CVSS-scored results
- **Dependency analysis**: Analyze dependency files and check for updates
- **Docker support**: Look up image tags and analyze
Dockerfile/docker-compose.yml dependencies
Expand Down Expand Up @@ -399,6 +399,14 @@ List all available versions of a package.

Check a package version for known security vulnerabilities.

Queries both OSV and NVD in parallel for comprehensive coverage. Results are
deduplicated by CVE ID — when a vulnerability appears in both databases, NVD's
CVSS v3.1 score is used as the authoritative severity rating.

Set the `NVD_API_KEY` environment variable for higher NVD rate limits (50 vs 5
requests per 30 seconds). Request a free key at
https://nvd.nist.gov/developers/request-an-api-key.

**Parameters:**

- `registry` (required): Package registry
Expand Down Expand Up @@ -429,8 +437,11 @@ Check a package version for known security vulnerabilities.
"id": "GHSA-29mw-wpgm-hmr9",
"summary": "Prototype Pollution in lodash",
"severity": "HIGH",
"cvss": 7.2,
"cveIds": ["CVE-2021-23337"],
"fixedVersions": ["4.17.21"]
"cweIds": ["CWE-94"],
"fixedVersions": ["4.17.21"],
"source": "osv+nvd"
}
],
"totalCount": 1,
Expand Down Expand Up @@ -648,6 +659,7 @@ src/
| Swift | `api.github.com/repos/{owner}/{repo}/tags` | [docs](https://docs.github.com/en/rest/repos/repos) |
| GitHub Actions | `api.github.com/repos/{owner}/{repo}/tags` | [docs](https://docs.github.com/en/rest/repos/repos) |
| OSV | `api.osv.dev/v1/query` | [docs](https://osv.dev/docs/) |
| NVD | `services.nvd.nist.gov/rest/json/cves/2.0` | [docs](https://nvd.nist.gov/developers/vulnerabilities) |

## License

Expand Down
5 changes: 4 additions & 1 deletion src/registries/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export interface RegistryClient {
export type Severity = "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";

/**
* Vulnerability information from OSV
* Vulnerability information from OSV and/or NVD
*/
export interface Vulnerability {
id: string;
Expand All @@ -96,10 +96,13 @@ export interface Vulnerability {
severity?: Severity;
cvss?: number;
cveIds?: string[];
cweIds?: string[];
affectedVersions?: string;
fixedVersions?: string[];
publishedAt?: Date;
references?: string[];
/** Which database(s) reported this vulnerability */
source?: "osv" | "nvd" | "osv+nvd";
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/tools/analyze-dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Supported file formats:

Note: For Gradle files, use registry='maven'. For GitHub Actions workflow files, use registry='github-actions'. Variable references ($version, libs.xxx) are skipped.

Optionally checks for known vulnerabilities using the OSV database.
Optionally checks for known vulnerabilities using OSV and NVD databases.

Returns a list of dependencies with:
- Current version
Expand Down
20 changes: 12 additions & 8 deletions src/tools/check-vulnerabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,16 @@ export function registerCheckVulnerabilitiesTool(server: McpServer): void {
"check_vulnerabilities",
`Check a package version for known security vulnerabilities.

Uses the Open Source Vulnerabilities (OSV) database which aggregates vulnerabilities from:
- GitHub Security Advisories
- NVD (National Vulnerability Database)
- PyPI Advisory Database
- RustSec Advisory Database
- Go Vulnerability Database
- And more
Queries two databases in parallel for comprehensive coverage:
- OSV (Open Source Vulnerabilities): aggregates GitHub Security Advisories, PyPI, RustSec, Go, and more
- NVD (National Vulnerability Database): authoritative CVSS v3.1 scores and CWE classifications

Returns CVE IDs, severity ratings, affected version ranges, and available fixes.`,
Results are deduplicated by CVE ID. When a vulnerability appears in both databases,
NVD's CVSS score is used as the authoritative severity rating.

Set the NVD_API_KEY environment variable for higher NVD rate limits (50 vs 5 requests/30s).

Returns CVE IDs, CVSS scores, CWE IDs, severity ratings, affected version ranges, and available fixes.`,
inputSchema.shape,
async ({ registry, package: packageName, version, severityThreshold }) => {
try {
Expand All @@ -73,11 +74,14 @@ Returns CVE IDs, severity ratings, affected version ranges, and available fixes.
id: v.id,
summary: v.summary,
severity: v.severity,
cvss: v.cvss,
cveIds: v.cveIds,
cweIds: v.cweIds,
affectedVersions: v.affectedVersions,
fixedVersions: v.fixedVersions,
publishedAt: v.publishedAt?.toISOString(),
references: v.references,
source: v.source,
})),
totalCount: vulns.length,
hasVulnerabilities: vulns.length > 0,
Expand Down
Loading