Because cargo audit tells you what's wrong but not what to do about it.
I have a project with 300 dependencies. I run cargo audit and it spits out a wall of CVEs. Cool. Now what? Do I fix them all? Which ones actually matter? Which ones can I fix with one command versus which ones require rewriting half my codebase?
That's the problem pulse solves. It doesn't just find vulnerabilities — it tells you the order to fix them, how hard each one is, and exactly which command to run. One finding, one command, done.
pulse reads your Cargo.lock, queries the OSV database, and builds a triage report. Every finding gets sorted into one of four buckets:
- fix now — high impact, patch available, run this command
- when you can — patch exists but lower priority
- blocked upstream — no patch yet, watch this issue
- worth knowing — informational, not a real vulnerability
The report shows you exactly what to run. No guessing, no reading 47 separate advisories to figure out which cargo update actually helps.
git clone https://github.com/yourpwnguy/pulse.git
cd pulse/
cargo install --path .When it's on crates.io:
cargo install pulseCheck the releases page for pre-built binaries for Linux, macOS, and Windows.
pulseFinds all Cargo.lock files in the current directory and scans them. That's it.
pulse /path/to/projectFor CI pipelines or scripting:
pulse --format jsonpulse --fixThis runs cargo update for each fixable package. If that doesn't work because of Cargo.toml version caps, it automatically tries cargo add to update the requirement.
pulse --projectsShows which projects were found, which were scanned, and which were excluded.
pulse doesn't just check your direct dependencies. It walks the entire dependency tree and figures out why each package is present. If time is vulnerable and it's there because of chrono, you'll see that in the report.
Not all vulnerabilities are equal. pulse considers:
- Severity — CVSS score when available
- Fix availability — is there a patched version?
- Effort — can you upgrade with
cargo updateor does it require a breaking change? - Ownership — is this your direct dependency or transitive?
A critical vulnerability with an easy fix gets priority over a medium one with no patch.
When --fix runs, it doesn't just trust the exit code. It checks the lockfile afterwards to confirm the version actually changed. If cargo update succeeds but the package doesn't move (because of a version cap), it tries cargo add instead.
While scanning, pulse shows a live terminal animation with Doki the cat. It blinks, sniffs, reads, and reacts to what it finds. Sounds silly, makes the 2-second scan feel faster.
╭──────────────────────────────────────────────────────────────────────────────╮
│ ♡ pulse doki is watching ✧ │
│ 3 issues 3 fixable now │
│ ▰▰▰▰▰▰▰▰▰▰▰▰ 3 of 3 fixable right now ✧ │
│ oldest 204d 3 unrated │
│ 215 packages · 1 project │
╰──────────────────────────────────────────────────────────────────────────────╯
╱╲___╱╲
( ˶>ω<˶ ) ♡ everything is fixable!
╲ ╱
╲___╱
▸ cargo update -p bytes fixes 1 of 3
or pulse --fix to apply all 3
◇ when you can 3
bytes 1.10.1 → 1.11.1 drop-in medium via reqwest → bytes
cargo update -p bytes
bytes has integer overflow in BytesMut::reserve GHSA-434x-w66g-qw3r 204d
h2 0.4.12 → 0.4.16 quick unknown via reqwest → h2
cargo update -p h2
h2 unbounded empty DATA frames RUSTSEC-2026-0258 9d
crossbeam-epoch 0.9.18 → 0.9.20 quick unknown
via rayon → rayon-core → crossbeam-deque → crossbeam-epoch
cargo update -p crossbeam-epoch
Invalid pointer dereference in `fmt::Pointer` impl for `Atomic` and `Shared` when t… RUSTSEC-2026-0204 51d
! 3 unrated
pulse --fix upgrade these for you, then re-check
See ARCHITECTURE.md for the technical details. The short version:
- Pure functional core, impure shell
- No async runtime — blocking HTTP is fine for 3 requests
- OSV is the only network dependency
- Everything else is parsing and pure logic
Cargo only — Rust is the ecosystem I work in. Adding npm, pip, or go support would require different lockfile parsers and advisory sources. Not impossible, just not what I needed.
No reachability analysis — pulse tells you if a package is vulnerable, not if your code actually calls the vulnerable function. That's a much harder problem that requires call graph analysis.
Single advisories source — uses OSV. The RustSec advisory database is the most comprehensive for Rust, and OSV includes it. If you need NVD or other sources, that would be a separate integration.
- Shell completions for bash, zsh, fish
--summaryflag for quick one-liner output- Integration with GitHub Actions for PR comments
- npm support (lockfile v2/v3 parsing)
- Python support (requirements.txt, poetry.lock)
- Reachability hints using
cargo rustc -- --emit=metadata
- Web UI for teams
- Slack/Discord notifications for new advisories
- Custom severity overrides
A security tool should have a pulse. The name is literal — there's a heartbeat animation while it scans. Also, "pulse" is short, memorable, and wasn't taken on crates.io.
If you want to contribute, feel free to open issues for bugs or feature requests. Pull requests are welcome for fixes and new features.
MIT