refuse

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 5 GitHub stars
Code Uyari
  • network request — Outbound network request in apps/server/src/__smoke.ts
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Open-source server that refuses vulnerable package installs. The backend the refuse CLI shim calls. Apache-2.0.

README.md

refuse

Self-hostable backend that powers refuse-cli to block vulnerable package installs.

CI
CodeQL
License: Apache-2.0
Container
Release

A small HTTP service that ingests public vulnerability + metadata feeds — OSV, deps.dev, CISA KEV, FIRST EPSS, GitHub Security Advisories, Wolfi — into a local SQLite database and answers questions like:

  • Is [email protected] vulnerable?
  • What's the minimum-safe upgrade for requests?
  • Are any of the 250 packages in this package-lock.json known-bad?
  • Does this Dockerfile install a CVE-laden apt package?

The intended caller is refuse-cli — a tiny shim that wraps npm, pnpm, yarn, pip, cargo, gem, bun, go and refuses to run an install for a known-bad package. The server is also a plain REST API, so curl, a CI step, or any other client can use it.


Where it runs

A long-running HTTP service — pick one host:

  • Laptopdocker run, bound to localhost. Anonymous mode is fine.
  • Team VM — same image behind your reverse proxy, API-key locked down.
  • Hostedrefuse.dev runs the same image for you.

CLI-side integrations (PATH shim, pre-commit, GitHub Actions, Docker builds) live in refuse-cli.


What it does

  • REST APIPOST /api/v1/check/{package, batch, lockfile, dockerfile, workflow} and suggest-safe-version. JSON in/out, optional bearer auth.
  • Ingestion runs in-process: OSV every ~5 min, deps.dev every ~15 min, daily KEV / EPSS / GHSA / Wolfi enrichment. All sources public, no runtime calls outside them.
  • Embedded SQLite (WAL mode), one container, one volume.
  • Admin UI at /ui/ for source health, manual ingest triggers, and API-key CRUD.

An /mcp endpoint for MCP-aware clients is on the roadmap. REST is the canonical interface today.


Quickstart

1. Start the server with a persistent volume

docker run -d --name refuse -p 8080:8080 \
  -v refuse-data:/data \
  ghcr.io/refusehq/refuse:latest

2. Watch the cold-seed (~3 minutes)

docker logs -f refuse

The first boot streams OSV's bulk archive (every ecosystem in one pass — npm, PyPI, Maven, Go, crates.io, RubyGems, … plus every Debian / Ubuntu / Alpine / RHEL distro the OSV team publishes), plus KEV, EPSS, GHSA, and Wolfi in parallel. The bars show what's happening:

refuse: ingest[osv:bulk         ] [██████████░░░░░░░░░░]  50% • 75000 records • 1m30s
refuse: ingest[kev              ] [████████████████████] 100% • 1542/1542 entries
refuse: ingest[epss             ] [████████████████████]  87% • 245678 rows scored
refuse: ingest[ghsa             ] ✓ done — 100 records in 2s (cursor saved)
refuse: ingest[wolfi            ] ✓ done — 1247 records across 412 packages in 4s

After this one-time bootstrap, deltas every 5 minutes are seconds-fast.

3. Wait for /readyz

curl http://localhost:8080/readyz

Returns 503 with a pending_sources list while sources are bootstrapping, and 200 once every required source has completed at least one pass:

{
  "ready": true,
  "ready_sources": ["osv", "kev", "epss", "ghsa_direct", "wolfi"],
  "pending_sources": [],
  "osv_ecosystems_done": 26,
  "osv_ecosystems_total": 26
}

4. Point refuse-cli at it

refuse config set server_url http://localhost:8080
refuse install                   # drop PATH shims into ~/.refuse/bin
npm install [email protected]
# refuse: blocked — CVE-2019-10744 (critical); suggested 4.17.21

Direct REST calls work too — useful for any client that doesn't want the shim:

curl -sX POST http://localhost:8080/api/v1/check/package \
  -H 'Content-Type: application/json' \
  -d '{"ecosystem":"npm","name":"lodash","version":"4.17.10"}' | jq .

Or browse to http://localhost:8080/ui/ for the dashboard.


Production deploy (compose)

services:
  refuse:
    image: ghcr.io/refusehq/refuse:latest
    ports: ["8080:8080"]
    volumes: ["./data:/data"]
    restart: unless-stopped
    environment:
      REFUSE_REQUIRE_KEY: "true"
      REFUSE_ADMIN_TOKEN: "${REFUSE_ADMIN_TOKEN:?set it before starting}"
      # REFUSE_GITHUB_TOKEN: ghp_... (optional, raises GHSA ingest rate limit)
    healthcheck:
      test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:8080/healthz').then(r=>process.exit(r.ok?0:1))"]
      interval: 30s
      retries: 3

See docker/docker-compose.with-key.yml for the same with comments.


Configuration

Everything is env-driven. Defaults pick safe values so docker run works without any flags.

Variable Default Purpose
REFUSE_PORT 8080 HTTP listen port
REFUSE_DB_PATH /data/refuse.db SQLite file path
REFUSE_REQUIRE_KEY false Require Authorization: Bearer rfs_… on /api/v1/check/*
REFUSE_ADMIN_TOKEN (unset) Static bearer for admin UI + key CRUD
REFUSE_OSV_FREQUENCY 5 Minutes between OSV delta runs
REFUSE_DEPS_DEV_FREQUENCY 15 Minutes between deps.dev runs
REFUSE_ENRICHMENT_CRON 0 5 * * * Cron expression for KEV/EPSS/GHSA/Wolfi
REFUSE_BOOTSTRAP_ON_EMPTY true Synchronous OSV pull on first boot if DB is empty
REFUSE_DISABLE_INGEST false Read-only mirror mode (for pre-seeded snapshots)
REFUSE_GITHUB_TOKEN (unset) Optional GH token, raises the GHSA-direct rate limit
REFUSE_CARD_CACHE_SIZE 5000 LRU entries for built VulnCards
REFUSE_CARD_CACHE_TTL_SECONDS 600 TTL on that LRU
REFUSE_LOG_LEVEL info debug / info / warn / error
REFUSE_CORS_ORIGIN * CORS allow-origin on /api/v1/check/*

Full reference: docs/configuration.md.


API surface

GET /healthz Liveness probe
POST /api/v1/check/package Single-package vuln check
POST /api/v1/check/batch Many packages in parallel
POST /api/v1/check/lockfile Parse + scan an entire lockfile
POST /api/v1/check/dockerfile Parse + scan base image + RUN lines
POST /api/v1/check/workflow Scan GitHub Actions uses: entries
POST /api/v1/suggest-safe-version Minimum-safe upgrade for an affected package
GET /api/admin/stats DB row counts (admin token)
GET /api/admin/sources Last-run / last-OK per ingest source
POST /api/admin/ingest/{osv,deps-dev,enrichment} Manual trigger
GET/POST/DELETE /api/keys[/:id] API key CRUD
GET /ui/ Admin dashboard for self-hosted operators

Full schema reference: docs/api.md.


The refuse family

What it is When to use it
refuse (this) Self-hostable HTTP server You want your own backend — air-gapped, on-prem, or just because
refuse-cli PATH shim that wraps npm / pip / cargo / … You want to block installs before they happen, on a dev machine or CI

Both share parsers, version comparators, and the OSV-derived data model.


How it compares

refuse OSV-scanner Trivy / Grype Dependency-Track guarddog npq
OSS license Apache-2.0 Apache-2.0 Apache-2.0 Apache-2.0 Apache-2.0 MIT
Standalone server partial
Install-time gate via PATH shim (with refuse-cli)
Dockerfile parsing (base image + RUN) ✅ (different mechanism)
OSV data
KEV / EPSS enrichment partial
GitHub Actions uses: scanning partial
Heuristic malicious-package detection partial partial
Single-container deploy n/a n/a n/a

refuse's differentiator is install-time gating — refusing the install before it runs, rather than reporting on a tree after the fact. The CLI shim makes that gate transparent to the developer or CI step. If you already run Trivy or Dependency-Track for the post-install monitoring angle, refuse composes with them: the structured refusal records (package, version, reason, OSV id) drop into either pipeline.


Self-host walkthrough

Single developer (laptop)

mkdir -p ~/refuse-data
docker run -d --name refuse \
  -p 8080:8080 -v ~/refuse-data:/data \
  --restart unless-stopped \
  ghcr.io/refusehq/refuse:latest

# install the CLI (from the refuse-cli repo)
brew install refusehq/tap/refuse
refuse config set server_url http://localhost:8080
refuse install

Anonymous mode is fine here — the server only binds to localhost.

Fleet (real domain, persistent volume)

Behind nginx/Caddy with TLS:

services:
  refuse:
    image: ghcr.io/refusehq/refuse:latest
    volumes: ["/srv/refuse:/data"]
    environment:
      REFUSE_REQUIRE_KEY: "true"
      REFUSE_ADMIN_TOKEN: "${REFUSE_ADMIN_TOKEN}"
      REFUSE_GITHUB_TOKEN: "${REFUSE_GITHUB_TOKEN}"
      REFUSE_CORS_ORIGIN: "https://your-app.example.com"
    restart: unless-stopped

Point a DNS record at the host, terminate TLS in your reverse proxy, and rotate REFUSE_ADMIN_TOKEN periodically. Back up /srv/refuse/refuse.db with a cron cp — SQLite WAL makes a hot copy safe.

Detailed guide: docs/self-hosting.md.


Build from source

git clone https://github.com/RefuseHQ/refuse.git
cd refuse
pnpm install
pnpm typecheck && pnpm test
pnpm --filter @refuse-oss/server dev      # hot reload on src/

# build the Docker image locally
make docker
make docker-run                            # → http://localhost:8080

Repo layout:

apps/server/             # Hono server, REST API, tools, ingest, UI
  src/
    config.ts            # env validation
    db/                  # SQLite client + D1-shape facade + migrations
    http/                # router, REST, auth, admin
    tools/               # the six check_* tools
    ingest/              # cron scheduler + OSV/deps.dev/KEV/EPSS/GHSA/Wolfi
    cards/               # VulnCard reader (LRU on top of SQLite)
    ui/static/           # tiny vanilla SPA
packages/
  shared/                # zod schemas, ecosystem normalization
  versions/              # version matchers (semver, pypi, maven, dpkg, …)
docker/                  # Dockerfile + compose examples + entrypoint

See ARCHITECTURE.md for the deeper walkthrough.


Contributing

Issues, fixes, and new ecosystem matchers are welcome. See CONTRIBUTING.md. Before opening a PR:

pnpm typecheck && pnpm test
./scripts/audit.sh        # guards against vendor-locked URLs and runtime env-var leakage
make docker               # confirms the image still builds

Security

Security policy: SECURITY.md. Report privately via [email protected] or GitHub private vulnerability reporting.

Acknowledgments

Built on top of OSV.dev, deps.dev, the CISA KEV catalog, FIRST EPSS, GitHub Security Advisories, and the Wolfi advisories.

License

Apache License 2.0 © RefuseHQ.

Yorumlar (0)

Sonuc bulunamadi