Skip to content

About

Watches dependency manifests in your git repos and sends a Telegram alert when pinned versions hit a published CVE; with score, current version, and minimum fix.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dep-cve-watcher

Watches the dependency manifests in your git repositories, checks the pinned versions against published security advisories, and sends a Telegram alert when something needs an urgent bump.

Sibling to cve-watcher (watching running services) — same alert philosophy: not every new version, only CVEs bad enough to act on, with the score, the version you have, and the minimum version to upgrade to.

What it does

  1. Inventory — discovers repositories on your Gitea instance via a read-only token and reads their dependency files. Parsers land for the stacks most self-hosted apps actually use:
    • npm — package.json, package-lock.json (v1/v2/v3), yarn.lock (classic + berry), pnpm-lock.yaml
    • Go — go.mod
    • Python — requirements.txt, Pipfile.lock, poetry.lock, pyproject.toml
    • Cargo.toml / Gemfile / composer.json are detected and listed in the weekly digest as "ecosystem not watched yet" — parsers follow (see PLAN.md).
  2. Match — resolves each pinned dependency version against GitHub Security Advisories (primary — package+ecosystem native), NVD, and CISA KEV. Within a run each package is fetched once (batched GHSA queries into memory); results are not reused across runs, so a new advisory is seen on the next cycle (default every 6 h). KEV is one daily bulk file. Fifty projects depending on the same library still cost one query per cycle, not fifty.
  3. Alert — one Telegram message per affected repository+dependency, grouped with the max CVSS and the minimum fixed version to upgrade to. Deduplicated so you hear about each problem once; KEV (known-exploited) findings flagged as urgent. Weekly digest covers open findings and dependencies pinned to ranges that can't be checked.

A message looks like this:

⚠️ Security updates needed

gitea:main · myorg/webapp · npm/lodash
Manifest: package-lock.json (locked)
Current: 4.17.15
Findings: 2 (max CVSS 9.8)
Update to at least: 4.17.21

• CVE-2021-23337 — CVSS 7.2
• CVE-2020-28500 — CVSS 7.5

Command injection in template.
https://nvd.nist.gov/vuln/detail/CVE-2021-23337

Quick start (local dry-run)

git clone https://github.com/CaffeinatedTech/dep-cve-watcher
cd dep-cve-watcher
cp config.example.yaml config.yaml   # edit: chat id, gitea url, discover
cp env.example .env                  # fill tokens (see docs/DEPLOY.md)
go run . --once --print-inventory    # merged inventory, no alert traffic
go run . --once                      # one real cycle, then exit

--print-inventory prints every discovered repo with its resolved dependencies and manifest notes — the fast way to sanity-check discover: and ignore: rules before trusting alerts. Full credentials setup (Telegram bot, Gitea machine-user PAT, GitHub/NVD keys) is docs/DEPLOY.md.

Configuration walkthrough

One YAML file (config.example.yaml, fully commented). Credentials never live here — they come from env vars (env.example):

Env var Purpose
DEPCVEWATCHER_TELEGRAM_BOT_TOKEN required for alerts (dry-run works without)
DEPCVEWATCHER_GITEA_<NAME>_TOKEN one read-only PAT per gitea: instance
DEPCVEWATCHER_GITHUB_TOKEN optional, raises GHSA limit 60 → 5000/h
DEPCVEWATCHER_NVD_API_KEY optional, only if sources.nvd: true

The knobs:

interval: 6h               # check cadence (in-process ticker)
severity_threshold: 7.0    # alert on CVSS >= this, or any KEV entry
state_file: state.json     # local default; use /data/... in containers
cache_dir: cache           # KEV/NVD disk cache only (GHSA is in-memory)
digest_day: Mon            # weekly digest; "" disables

telegram:
  chat_id: "000000000"

gitea:                     # zero or more instances
  - name: main             # token env var: DEPCVEWATCHER_GITEA_MAIN_TOKEN
    url: https://gitea.example.com
    discover:
      orgs: [example-org]  # all repos in these orgs
      # users: [someone]   # and/or repos owned by these users
      # repositories:      # and/or an explicit owner/repo allowlist
      #   - otherorg/legacy-app

ignore:                    # applied at inventory collection
  repos: []                # owner/repo to skip entirely
  packages: []             # package name, any ecosystem
  ecosystems: []           # e.g. [maven] — also hides its digest notes
  paths: []                # repo path prefixes, e.g. "legacy/"

sources:
  ghsa: true               # primary: package+ecosystem native
  nvd: false               # secondary; needs a CPE mapping to be useful
  kev: true                # flag actively-exploited CVEs as urgent

Rules worth knowing:

  • Ranges are never guessed. ^1.2.0 without a lockfile goes to the digest's "cannot check" list — silence still means all-clear.
  • Ecosystem travels with every dependency — requests (pip) is not any other requests; in-memory keys and advisory queries are scoped.
  • Failed Telegram sends queue for the next cycle; state is saved atomically so restarts never re-spam or drop findings.

Deployment

Three supported shapes — one binary + one config + a writable data dir in every case:

Target Artifact
k3s / Kubernetes deploy/ manifests + NetworkPolicy
Docker Compose docker-compose.yml
systemd / Coolify unit + steps in docs/DEPLOY.md

Images are built by hand with dated tags (ghcr.io/caffeinatedtech/dep-cve-watcher:YYYY-MM-DD) — no CI; the build/push procedure is docs/DEPLOY.md §4.

Why not just use ...

  • Dependabot — not self-hostable outside GitHub.
  • Renovate — opens fix PRs; doesn't send you an ops-style alert with score + current + minimum fix. Useful as a companion, not this.
  • Trivy / Grype — general-purpose scanners; you'd still wrap them in discovery, caching, dedup, and Telegram yourself. That wrapper is what this is.
  • Gitea Enterprise dependency scanning — paid, dashboard-first, no Telegram push.

If one of those fits better, use it. dep-cve-watcher exists for the specific gap: pinned version in your repos → published advisory → urgent Telegram alert, centrally, without installing anything in every repository.

Architecture

One central service with read-only access to your forge — not a workflow file in every repo. New repositories are covered the moment they're created; alerts are deduplicated and digested in one place. Repo access is Gitea's tree + contents API (no git binary — the image stays FROM scratch). See PLAN.md for the full design and REQUIREMENTS.md for the spec.

Status

Implementation Phases 1–5.5 are complete (domain model, Gitea discovery, manifest/lockfile parsers, advisory matching, alerting + digest, reliability fixes); Phase 6 (this pass) finalizes deployment files and docs. Open items — more ecosystems, ignore-rule extensions, v0.1.0 tag — live as checkboxes in PLAN.md.

License

MIT

About

Watches dependency manifests in your git repos and sends a Telegram alert when pinned versions hit a published CVE; with score, current version, and minimum fix.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages