dartvulncheck 0.2.1
dartvulncheck: ^0.2.1 copied to clipboard
Checks pubspec.lock and the Flutter/Dart SDK you build with against known vulnerabilities, and fails CI when it finds one.
dartvulncheck #
govulncheck for Dart and Flutter. It checks the packages pinned in pubspec.lock, and the Flutter/Dart SDK you build with, against known vulnerabilities, and fails CI when it finds one. Pure Dart, no Flutter required.
What it adds over the warning from flutter pub get:
flutter pub get warning |
dartvulncheck |
|---|---|
| Printed only; CI still passes | Fails CI through its exit code |
| pub packages only | Also checks the Flutter/Dart SDK itself |
| Only after GitHub has reviewed the advisory | Also reads repository advisories as soon as maintainers publish them |
| Human-readable text only | Machine-readable output with --json |
Install #
dart pub global activate dartvulncheck 0.2.1
Or from git, at a release tag: dart pub global activate --source git https://github.com/ouchinao/dartvulncheck --git-ref v0.2.1. Either way, name a version rather than the head of main, so that the tool does not change under you between runs.
Usage #
dartvulncheck # current directory
dartvulncheck app packages/core # several directories (monorepo)
It reads pubspec.lock, so run dart pub get (or flutter pub get) first.
| Option | Meaning | Default |
|---|---|---|
--json |
Print JSON | Text |
--fail-on <level> |
Exit 3 if anything at this severity or above is found (low / moderate / high / critical) |
low |
--ignore <id> |
Advisory ID to ignore (GHSA or CVE). Repeatable. Added to ignored_advisories in pubspec.yaml |
None |
--strict |
Also count advisories whose affected range cannot be read ("unverified") | Not counted |
--no-repo-advisories |
Skip repository advisories (the early-warning stage) | Skipped automatically without GITHUB_TOKEN |
--sdk-version <ver> |
Pass the Flutter version by hand | .fvmrc (or .fvm/fvm_config.json) → flutter --version → dart --version |
--no-sdk |
Do not check the SDK | Checked |
--no-transitive |
Do not check transitive dependencies | Checked |
--verbose |
Show how many packages were queried and ignored, and which could not be looked up | Off |
Exit codes #
| Code | Meaning |
|---|---|
| 0 | No problems (also when every finding is ignored) |
| 1 | Could not check (pubspec.lock missing, network failure, bad arguments) |
| 3 | Vulnerabilities found (same value as govulncheck) |
"Could not check" never passes as "no problems", and there is no option to make it do so.
Ignoring an advisory #
Use pub's own key in pubspec.yaml. The same list also silences the flutter pub get warning.
ignored_advisories:
- GHSA-xxxx-xxxx-xxxx # iOS only; this app ships on Android
Ignored findings are counted in the summary line, kept in the JSON output with "ignored": true, and listed by --verbose, so a growing ignore list stays visible. The text report lists them under Ignored.
GitHub Actions #
vulncheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
channel: stable
- run: dart pub global activate dartvulncheck 0.2.1
- run: dart pub global run dartvulncheck app packages/core
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- No
pub getneeded: only the committedpubspec.lockis read. flutter-actionis there so the SDK version can be read fromflutter --version. For pure Dart projects,dart-lang/setup-dartis enough.GITHUB_TOKENis needed because the repository-advisory stage makes dozens of requests (60/hour without a token, 1,000/hour with one). The default Actions token is enough.- Run it on a weekly
scheduleas well as on pull requests: new advisories appear even when your code does not change. - This complements Dependabot alerts rather than replacing them. Dependabot opens fix PRs; this tool stops CI and also covers the SDK and unreviewed advisories.
Data sources #
| Stage | Source | Covers |
|---|---|---|
| Primary | GitHub Advisory Database (GET /advisories?ecosystem=pub&affects=…) |
Hosted packages |
| Early warning | Repository security advisories (GET /repos/{owner}/{repo}/security-advisories) |
Packages with a GitHub repository, plus dart-lang/sdk and flutter/flutter |
| Fallback | OSV.dev (POST /v1/querybatch) |
Used only when GitHub is unreachable or answers something that is not an advisory list. Not on rate limiting or a rejected token: those need a fix on your side |
Base URLs can be overridden with DARTVULNCHECK_GITHUB_API_URL, DARTVULNCHECK_OSV_API_URL and DARTVULNCHECK_PUB_URL (for tests and GitHub Enterprise). Overrides must be https; http is accepted for localhost only, and every override in effect is reported on stderr.
Limitations #
- It does not check whether vulnerable code is actually called. pub advisories do not say which functions are affected, so there is nothing to match a call graph against.
- Advisories that only affect some platforms are reported for all platforms. Use
ignored_advisorieswith a comment for the ones that do not apply. gitandpathdependencies cannot be looked up. They are listed with--verbose.- Repository advisories describe affected versions in free text written by the maintainers. The forms seen so far are read (
< 3.13.7 (stable), < 3.14.0-315.3.beta (beta),Prior to 3.11.0,Dart version prior to 2.18.2, Flutter version prior to 3.3.3,>=1.0.0 <= 2.7.1); anything else is reported as "unverified" and not counted unless--strict. - Withdrawn advisories are dropped, and advisories of
dart-lang/sdkthat name no package are matched against the SDK only, not against the packages published from that repository (meta,analyzer, …).
Security #
doc/threat-model.md is a STRIDE review of the tool itself: what it is trusted with, where untrusted input enters, what is mitigated and what is accepted.
Development #
dart pub get
dart analyze
dart test
UPDATE_GOLDENS=1 dart test test/report_test.dart # after an intended output change
The GitHub API responses under test/fixtures/responses/ are recorded, not written by hand. To refresh them, run the Record API fixtures workflow in Actions and copy the files from its artifact over the existing ones.
A release is a version bump in pubspec.yaml and lib/src/version.dart, an entry in CHANGELOG.md, and, once that is merged, a v<version> tag on main and dart pub publish from a checkout of that tag.
Code under lib/src/ is split by layer: lockfile/ (input) → sources/ (lookup) → match/ (matching) → report/ (output). check/ runs them in order, cli/ handles arguments and exit codes, and model/ holds the shared types. Only sources/ talks to the network, so every test runs offline.
License #
MIT