Cybersecurity-Projects/PROJECTS/simple-vulnerability-scanner
CarterPerez-dev 58d63b63ca rename --scan-vulns to --vulns, add subcommand aliases, make check updates-only by default 2026-01-27 23:46:34 -05:00
..
cmd/angela feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00
internal rename --scan-vulns to --vulns, add subcommand aliases, make check updates-only by default 2026-01-27 23:46:34 -05:00
learn feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00
pkg/types feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00
testdata feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00
.gitignore feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00
.golangci.yml feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00
Justfile rename --scan-vulns to --vulns, add subcommand aliases, make check updates-only by default 2026-01-27 23:46:34 -05:00
README.md feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00
go.mod feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00
go.sum feat: complete phase 1 intial build 2026-01-27 23:17:50 -05:00

README.md

angela

A fast CLI tool that updates Python dependencies in pyproject.toml and scans for known vulnerabilities using OSV.dev.

Built in Go for speed — parallel HTTP requests, local caching with ETag support, and a single binary with zero runtime dependencies.


Why

The Python ecosystem lacks a single tool that updates all dependencies in pyproject.toml the way pnpm update works for JavaScript. Existing options either show outdated packages without updating them (pip list --outdated), upgrade one at a time (pip install --upgrade), or require CI infrastructure (Dependabot, Renovate).

angela fills this gap: one command updates everything, with built-in CVE scanning.


Install

go install github.com/CarterPerez-dev/angela@latest

Or build from source:

git clone https://github.com/CarterPerez-dev/angela.git
cd angela
go build -o bin/angela ./cmd/angela

Usage

Update all dependencies

angela update

Reads pyproject.toml in the current directory, queries PyPI for the latest stable versions, and writes the updates back to the file.

Dry run (show what would change)

angela check

Shows available updates and vulnerabilities without modifying any files.

Scan for vulnerabilities only

angela scan

Checks all pinned dependencies against the OSV.dev vulnerability database.

Update with vulnerability scan

angela update --scan-vulns

Updates dependencies and reports any known CVEs in your current versions.

Skip major version bumps

angela update --safe

Only applies minor and patch updates, skipping anything that crosses a major version boundary.

Include pre-release versions

angela update --include-prerelease

Considers alpha, beta, release candidate, and dev versions when resolving the latest.

Specify a different file

angela update --file path/to/pyproject.toml

Clear the local cache

angela cache clear

Removes all cached PyPI responses from ~/.angela/cache/.


Example output

  Scanning 9 dependencies...

  Updates available:
    django    3.2.0  -> 5.1.5   (major)
    requests  2.28.0 -> 2.32.3  (minor)
    click     8.0.0  -> 8.1.8   (patch)
    pydantic  2.0.0  -> 2.10.6  (minor)
    flask     2.0.0  -> 3.1.0   (major)
    pytest    7.0.0  -> 8.3.4   (major)
    black     23.0.0 -> 25.1.0  (major)
    ruff      0.1.0  -> 0.9.4   (minor)
    mypy      1.0.0  -> 1.14.1  (minor)

  Vulnerabilities found:
    django
      GHSA-2hrw-hx67-34x6 [CRITICAL] Potential denial-of-service in django.utils.text.Truncator
        Fixed in: 4.2.16
    requests
      GHSA-9wx4-h78v-vm56 [MEDIUM] Requests `Session` object does not verify requests after making first request with verify=False
        Fixed in: 2.32.0

  Updated pyproject.toml
    9 packages checked
    9 updated
    36 vulnerabilities found
    Done in 2.4s

How it works

1. Parse pyproject.toml
   Extract all [project.dependencies] and [project.optional-dependencies]

2. Query PyPI Simple API (parallel)
   Fetch version lists using the lightweight JSON format
   ETag-based caching avoids redundant downloads

3. Resolve updates
   Parse versions per PEP 440 (epochs, pre-releases, post-releases)
   Filter to stable releases by default
   Classify changes as major, minor, or patch

4. Scan for vulnerabilities (optional)
   Batch query OSV.dev for all dependencies
   Hydrate results with full advisory details
   Deduplicate overlapping CVE/GHSA identifiers

5. Write updates
   Regex-based surgery preserves comments and formatting
   Atomic write via temp file + rename

Architecture

cmd/angela/main.go           CLI entry point
internal/
  cli/
    update.go                 Command definitions and orchestration
    output.go                 Terminal formatting with color
  pypi/
    version.go                PEP 440 parser and comparator
    client.go                 PyPI Simple API client with retry
    cache.go                  File-backed ETag cache
  osv/
    client.go                 OSV.dev batch vulnerability scanner
  pyproject/
    parser.go                 TOML parsing and PEP 508 splitting
    writer.go                 Comment-preserving regex updater
pkg/types/
  types.go                    Shared domain types

Development

Requires Go 1.24+ and just.

just test        # Run all tests with race detector
just lint        # Run golangci-lint
just build       # Build binary to bin/angela
just cover       # Generate HTML coverage report
just check       # Lint + test in one step
just run check   # Run angela check via go run

Part of Cybersecurity-Projects

This tool is project #1 in the Cybersecurity-Projects repository — a collection of 60 security-focused projects built for learning and reference. The code is written to be educational: clear structure, proper error handling, and thorough testing.

See the learn/ directory for deep dives into the techniques used here.


License

MIT