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
4 changes: 2 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ GITHUB_INSTALLATION_IDS=
GITHUB_ALLOWED_REPOS=
GITHUB_WEBHOOK_SECRET=
NVD_API_KEY=
MAX_ENRICH_PACKAGES=100
MAX_NVD_CVES=20
MAX_ENRICH_PACKAGES=2000
MAX_NVD_CVES=3
OSS_INDEX_EMAIL=
OSS_INDEX_TOKEN=
OTEL_SERVICE_NAME=rippleguard
Expand Down
4 changes: 2 additions & 2 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ Light technical workspace for extended daytime investigations. Graph is the main

Warm rust identifies the selected dependency and propagation. Deep green-gray represents application services; risk colors have text labels. White surfaces, pale gray canvas, restrained rules. Geist for interface, Geist Mono only for versions/PURLs/measurements.

Persistent navigation, compact repository snapshot strip, four summary measures, graph with adjacent inspector, then a ranked table. Narrow screens stack the inspector and retain a scrollable graph with an equivalent accessible inventory. Every graph node supports keyboard selection. Reduced motion disables propagation animation.
Compact navigation, repository discovery and project confirmation, visible scan stages, four summary measures, top priority, focused dependency graph with adjacent inspector, then a ranked table. Narrow screens stack the inspector and retain a scrollable graph with an equivalent accessible inventory. Every graph node supports keyboard selection. Reduced motion disables propagation animation.

Assumed from the supplied graph-first engineering brief while the optional audience clarification remains unanswered. No separate visual reference was supplied.
Preserves the existing identity and prioritizes the repository-to-ripple journey from the current developer and hackathon brief.
2 changes: 1 addition & 1 deletion PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ web
## Stack
Delegated by the supplied specification. React/TypeScript, Fastify, Node 24 SQLite. A single container serves the API and built UI; replaceable connector/cache boundaries.
## Users
Assumption pending optional clarification: engineers tracing vulnerable dependencies to affected application services.
Developers tracing vulnerable dependencies to applications and services; hackathon viewers following a two-minute repository-to-ripple demonstration.
## Product Purpose
Map dependency graphs, rank deterministic risk, simulate reverse dependency impact, and export SPDX 2.3 JSON.
## Capabilities and Constraints
Expand Down
67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# RippleGuard

Understand a repository, check its dependencies, and trace how a package connects to applications. The existing React/Fastify app now follows **Scan → Repository Map → Analyze → Priority → Trace Ripple**.

## Run locally

Requires Node.js 24 or newer. From this directory:

```sh
npm ci
npm run local
```

Open http://127.0.0.1:3000/app#new. Public GitHub scans need internet access; **Explore demo** works offline. No API key is required for public scans. Optional configuration is documented in `.env.example`. SQLite snapshots and source caches persist under `data/`. Keep the default loopback binding for local use; production requires an API token.

## Two-minute recording

1. **0:00–0:20:** Open **Explore demo** from the landing page. Say that this is the clearly labeled offline illustrative scenario.
2. **0:20–0:40:** Show the four projects in Repository Map. Rename Storefront if desired, leave all four selected, and click **Analyze repository**.
3. **0:40–1:00:** Point to lodash, its installed version, and the reasons for its priority: severity, source-reported exploitation, depth, and three affected projects.
4. **1:00–1:35:** Click **Trace Ripple**. Follow the package paths back to the three affected applications; show the four paths and unaffected fourth project.
5. **1:35–2:00:** Open the package details and explain how it entered the applications. Clarify that dependency paths describe possible impact, not proof that vulnerable code executes.

For a recording using real source-backed findings, publish the prepared [controlled repository](demo-repository/README.md), paste its GitHub URL, and select the three `apps/` projects. Live verification found axios connected to all three through the shared package. Advisory counts and rankings can change as security sources update. The offline demo remains the reliable backup.

## Accuracy and limits

| Input | What is reconstructed |
| --- | --- |
| npm package-lock/shrinkwrap v2/v3 | Installed paths, nearest dependency resolution, workspace links, direct/indirect depth, and runtime/development scope. Independent installations remain distinct. |
| npm older lockfiles | Supported by the existing parser; less workspace context than v2/v3. |
| pnpm locks | Importer dependencies and recorded snapshot relationships; unsupported local workspace links remain explicit warnings. |
| package.json without usable lock / Yarn | Exact manifest pins are checked; ranges and other declarations remain visible as unresolved. Yarn lock resolution is not implemented. |
| Python requirements / Pipfile.lock | Exact pins are checked; unpinned declarations are retained with their constraints. Flat files do not establish indirect ancestry. Includes and commands are not executed. |
| uv / Poetry locks | Recorded packages and reconstructable edges; environment selection and application membership may remain unknown. Root links labeled “listed” do not establish direct depth. |
| Maven dependency tree | Recorded resolved dependency relationships. |
| Maven pom.xml | Literal versions only; parent properties, BOM-managed versions, profiles, and indirect dependencies may be unresolved. Maven is never executed. |

Related files are grouped by path and ecosystem. Repository Map reads declarations and reports detected, exact and unresolved counts before analysis. Project coverage is EXACT, PARTIAL, DECLARED_ONLY or UNSUPPORTED. Unresolved nodes retain an unversioned identity, their declared specifier and partial coverage; they are not vulnerability-checked or priority-scored. Repository discovery has no manifest-count cutoff. Truncated GitHub trees use bounded directory traversal and disclose remaining gaps. File/transport limits, unsupported formats, and individual parser failures produce project-level coverage notes; they do not turn unchecked packages into safe ones.

OSV provides package/version findings; CVSS vectors are scored deterministically. Registry sources can supplement findings; NVD enriches already-mapped CVEs only. CISA KEV adds positive known-exploitation evidence by exact CVE. Missing signals remain unknown. Fixed versions come only from matching affected-package evidence. No exploitation probability is invented.

Ripple Priority is a bounded triage score, not a probability: severity up to 60 (CVSS × 6), source-reported exploitation 15, exposure up to 10 (inverse known depth, halved for development-only usage), and repository impact up to 15 (12 for affected-project proportion plus 3 for ancestor proportion). Findings rank ahead of packages without findings. Source facts, factors, and paths remain inspectable. Depth describes the recorded graph, not code execution.

All occurrences of a selected package version are considered for impact, while installed-instance edges prevent false cross-project paths. Reverse traversal is cycle-safe. Path enumeration is bounded and labeled “at least” when truncated. The focused graph displays up to 70 nodes; the complete retained inventory and export remain available. Checking defaults to 2,000 unique package versions, configurable within bounds; omitted or failed checks remain visibly partial.

The built-in demo contains synthetic `DEMO-*` security data and illustrative edges. The prepared real demo uses an npm-generated lockfile and live source findings. Neither is a production certification.

## Verification

```sh
npm run check
npm run test:e2e
# Start the app first for the live repository matrix:
node --import tsx scripts/verify-real-repos.ts
node --import tsx scripts/verify-controlled-demo.ts
node --import tsx scripts/verify-live-browser.ts
VERIFY_BROWSER=1 node --import tsx scripts/verify-ingestion.ts
```

Browser tests require Playwright Chromium (`npx playwright install chromium`), or set `PW_CHROME=1` to use installed Chrome. Tests use a separate local server and database on port 3100.

Recorded results: [public repository matrix](docs/verification/live-repositories.json), [controlled demo evidence](docs/verification/controlled-demo.json). These are dated observations, not assertions about future repository contents or vulnerability-source responses.

The matrix covers expressjs/express (small npm), this repository (lockfile), npm/cli (478 projects / 575 files), pallets/flask (Python), spring-projects/spring-petclinic (Maven), GoogleCloudPlatform/microservices-demo (mixed language), and octocat/Hello-World (empty supported-manifest state). Coverage warnings are preserved in the report.

Main implementation: `src/server/discovery.ts`, `resolve-project.ts`, `advisories.ts`, `connectors.ts`, `jobs.ts`, and `graph.ts`; shared types in `src/shared/types.ts`; journey and focused graph in `src/web/main.tsx` and `src/web/components/`. Existing authenticated APIs, export, and webhook boundaries remain in place without expanding enterprise features.
38 changes: 38 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"files": {
"includes": [
"src/**/*.ts",
"src/**/*.tsx",
"tests/**/*.ts",
"scripts/**/*.mjs",
"scripts/**/*.ts",
"playwright.config.ts",
"!src/web/components/ui/hero-section-6.tsx",
"!src/web/components/ui/animated-group.tsx"
]
},
"formatter": {
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": false,
"correctness": {
"noUnreachable": "error",
"noInvalidUseBeforeDeclaration": "error",
"noConstantCondition": "error"
},
"suspicious": {
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"useIsArray": "error"
},
"a11y": {
"useKeyWithClickEvents": "error"
}
}
}
}
20 changes: 20 additions & 0 deletions demo-repository/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# RippleGuard recording repository

Prepared real npm workspace scenario: storefront, checkout, and admin each depend on `@rippleguard/shared-http`, which depends on pinned axios and express releases. `package-lock.json` was generated by npm and records real installed dependency relationships. There is no application runtime or install script.

These deliberately old dependencies are analysis inputs. Use this folder for demonstrating dependency analysis, not as an application starter.

To prepare the GitHub recording:

1. Copy this folder into a separate Git repository and publish it to a public GitHub repository you control. Commit all manifests and the root lockfile. It has **not** been published automatically.
2. Paste that repository URL into RippleGuard and use the published commit SHA in the ref field for repeatable dependency input.
3. In Repository Map, select `apps/storefront`, `apps/checkout`, and `apps/admin`. Deselect the repository root and `packages/shared-http`; the shared package will be reached through the real workspace links.
4. Analyze, select the top vulnerable package, and click **Trace Ripple**. Inspect the source links and affected applications.

Local verification from the parent RippleGuard repository:

```sh
node --import tsx scripts/verify-controlled-demo.ts
```

The recorded verification checked 53 package versions, found findings on eight packages, and traced top-ranked axios through three paths to all three applications. See `../docs/verification/controlled-demo.json` for timestamped source evidence. Findings may evolve independently of the pinned dependency graph. Use RippleGuard’s clearly labeled offline synthetic demo if external APIs are unavailable during recording.
8 changes: 8 additions & 0 deletions demo-repository/apps/admin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@rippleguard/admin",
"version": "1.0.0",
"private": true,
"dependencies": {
"@rippleguard/shared-http": "1.0.0"
}
}
8 changes: 8 additions & 0 deletions demo-repository/apps/checkout/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@rippleguard/checkout",
"version": "1.0.0",
"private": true,
"dependencies": {
"@rippleguard/shared-http": "1.0.0"
}
}
8 changes: 8 additions & 0 deletions demo-repository/apps/storefront/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@rippleguard/storefront",
"version": "1.0.0",
"private": true,
"dependencies": {
"@rippleguard/shared-http": "1.0.0"
}
}
Loading
Loading