libscan is a single-binary, dependency-light command-line scanner
that audits a project's package manifests for known vulnerabilities,
end-of-life runtimes, and stale dependencies — then writes a human or
machine readable reports.
It walks your source tree, parses lock files for the languages it understands, queries public security and release-cycle data sources, and aggregates the results into one of four report formats (text, JSON, DOCX, PDF). It is designed for local audits, CI gating, and hand-off reports to engineering leads or product managers.
- Multi-ecosystem lock-file scanning — PHP / Composer
(
composer.lock) and JavaScript (package-lock.json,yarn.lock,pnpm-lock.yaml). - Vulnerability data from public sources — OSV.dev for CVE feeds, Packagist and the npm registry for "latest version" lookups, and endoflife.date for runtime / framework EOL status.
- Actionable verdicts — each finding is classified
BLOCK/REVIEW/OKusing configurable CVSS thresholds, optionally enriched with FIRST.org EPSS scores and CISA KEV membership. - Four report formats —
text(ANSI-coloured terminal output),json(machine-readable),docx, andpdf. Locale-aware: English, Japanese, Vietnamese. - EOL awareness — each detected runtime / framework is bucketed
as
Expired/Warn/Supported/Unknown, with an configurable look-ahead window. - CI-friendly — non-zero exit codes are opt-in via
--fail-on=REVIEW|BLOCK; air-gapped runs skip the best-effort enrichment endpoints with--offline-skip-epss. - No CGO, no system libraries — one statically linked binary per
platform; cross-compiled releases via
goreleaser.
Pre-built binaries are published for macOS, Linux, and Windows (x86_64 + arm64) on every tagged release.
brew tap vocweb/tap
brew install libscanscoop bucket add vocweb https://github.com/vocweb/scoop-bucket
scoop install libscanRequires Go 1.23+ on the user's machine:
go install github.com/vocweb/libscan-cli/src/cmd/libscan@latestGrab the latest archive from the
Releases page
and drop the binary somewhere on your PATH.
# macOS / Linux — pick the archive matching your platform
curl -sSL https://github.com/vocweb/libscan-cli/releases/latest/download/libscan-cli_<VERSION>_Darwin_arm64.tar.gz | tar xz
sudo mv libscan /usr/local/bin/# Windows PowerShell
$ver = (Invoke-RestMethod https://api.github.com/repos/vocweb/libscan-cli/releases/latest).tag_name.TrimStart("v")
$url = "https://github.com/vocweb/libscan-cli/releases/latest/download/libscan-cli_${ver}_Windows_x86_64.zip"
Invoke-WebRequest $url -OutFile "$env:TEMP\libscan.zip"
Expand-Archive "$env:TEMP\libscan.zip" -DestinationPath "$env:USERPROFILE\bin" -Force
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";$env:USERPROFILE\bin", "User")See BUILD.md for toolchain setup, cross-compilation,
and running tests. TL;DR:
make build # produces ./bin/libscan# Scan the current directory with default settings.
libscan
# Scan a specific project and write a PDF report.
libscan --scan-path=/var/www/app --format=pdf --output=report.pdf
# Fail the CI job when any finding is BLOCK-severity.
libscan --format=json --fail-on=BLOCKlibscan reads configuration from libscan.ini (auto-detected in
the current directory, or pass --config /path/to/file.ini). Any
key in the file has an equivalent CLI flag, and flags win over file
values.
See libscan.example.ini for the complete
schema. The main sections are:
[scan]— directory, ignore list, symlink behaviour.[output]— report format, output path, colour mode, language.[network]— HTTP timeout, retries, worker pool size.[sources]— override OSV / Packagist / npm / endoflife endpoints.[report]— severity filters, EOL warning window.[eol_mapping]— map packages to endoflife.date product ids.
| Flag | Default | Description |
|---|---|---|
--config |
Path to libscan.ini (auto-detected in CWD when omitted). |
|
--scan-path |
. |
Directory to scan recursively. |
-f, --format |
text |
Report format: text | json | docx | pdf. |
-o, --output |
Output path (default: libscan-report-{timestamp}.{ext} in CWD). |
|
--workers |
8 |
Concurrent worker pool size for registry lookups. |
--timeout |
30 |
Per-request HTTP timeout, in seconds. |
--color |
auto |
Terminal colour mode: auto | always | never. |
--lang |
en |
Report language: en | ja | vi. |
--no-low |
false |
Omit LOW severity findings from the rendered report. |
--block-cvss |
9.0 |
CVSS v3 threshold at or above which a finding is BLOCK. |
--warn-cvss |
7.0 |
CVSS v3 threshold at or above which a finding is REVIEW. |
--offline-skip-epss |
false |
Skip best-effort EPSS / KEV enrichment (air-gapped CI). |
--fail-on |
Exit non-zero when verdict reaches this severity: REVIEW | BLOCK. |
|
--epss-endpoint |
Override the FIRST.org EPSS endpoint (https only). | |
-v, --version |
Print version information and exit. |
| Code | Meaning |
|---|---|
0 |
Scan completed cleanly (no --fail-on policy triggered). |
2 |
User error — bad flag, malformed config, missing scan path. |
3 |
Runtime error — network failure, render error, walker error. |
4+ |
Policy exit, when --fail-on=REVIEW or --fail-on=BLOCK is tripped. |
Vulnerabilities found during a scan do not by themselves change
the exit code — only --fail-on does. This keeps libscan safe to
drop into existing pipelines without breaking them by surprise.
libscan queries the following public endpoints by default. All can
be overridden under [sources] in libscan.ini.
- OSV.dev — vulnerability advisories.
- Packagist — Composer package metadata.
- npm registry — npm package metadata.
- endoflife.date — runtime / framework EOL.
- FIRST.org EPSS — exploit probability
(best-effort, can be skipped with
--offline-skip-epss). - CISA KEV — known exploited vulnerabilities (best-effort).
Please respect the upstream services' rate limits and terms of use when running large scans.
Issues and pull requests are welcome. Before opening a PR:
- Run
make lintandmake testlocally — both must be clean. - Add or update entries in
CHANGELOG.mdunder[Unreleased]. - Keep the binary dependency-light. New runtime dependencies should be justified in the PR description.
MIT — see LICENSE.