Security Vulnerability Detection
Detect vulnerabilities and select lowest-risk dependency portfolios
Detect vulnerabilities and select lowest-risk dependency portfolios
Pastoralist can scan dependencies with security providers and record fixes in the override appendix.
Security checks scan your dependencies, report vulnerable packages, and can suggest or apply package-manager overrides when a patched version is available. The appendix keeps the CVE, provider, severity, patched version, and reason with the override.
# Check for vulnerabilities and display a reportpastoralist --checkSecurity --dry-runApplying fixes requires --interactive, --forceSecurityRefactor, or the
matching config option. Review changes and reinstall dependencies to update
the lockfile.
# Automatically apply security fixespastoralist --checkSecurity --forceSecurityRefactor# Choose which fixes to applypastoralist --checkSecurity --interactive# Include workspace packages in the scanpastoralist --checkSecurity --hasWorkspaceSecurityChecksYou can configure security settings in your package.json:
{ "pastoralist": { "security": { "enabled": false, "provider": "osv", "autoFix": false, "interactive": false, "hasWorkspaceSecurityChecks": false, "severityThreshold": "medium", "excludePackages": [] }, "bestCase": { "enabled": false, "userOwnedOverrides": [] } }}| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable automatic security checks when running pastoralist |
provider | string or array | "osv" | Provider: "osv", "github", "npm", "snyk" [EXPERIMENTAL], "socket" [EXPERIMENTAL], "spektion" [EXPERIMENTAL] |
autoFix | boolean | false | Automatically apply security fixes without prompting |
interactive | boolean | false | Use interactive mode to select which fixes to apply |
securityProviderToken | string | "" | Authentication token for providers that require it. Prefer provider environment variables; use this only for controlled config that will not be committed. |
hasWorkspaceSecurityChecks | boolean | false | Include workspace packages in security scan |
severityThreshold | string | "medium" | Minimum severity level to report (low, medium, high, critical) |
excludePackages | array | [] | List of package names to exclude from security checks |
strict | boolean | false | Fail when a provider cannot complete |
Independent upgrades can interact: one package fix may introduce a
vulnerability or compatibility failure in another package. Enable bestCase
to rank complete package-version portfolios under one policy:
{ "pastoralist": { "checkSecurity": true, "bestCase": { "enabled": true, "riskAggregation": "both", "search": { "mode": "auto", "exactStateLimit": 256, "beamWidth": 16, "maxEvaluations": 1000 } } }}Each patchable package contributes its current version, known patched versions,
and latest compatible version. Auto mode exhaustively evaluates small products
and uses deterministic beam search above the configured cap. The result includes
the selected state, decision ID, policy hash, vulnerability impact, duration,
evaluated-state count, and provenOptimal status.
Declare a package as user-owned when its active override must win over portfolio ranking. Interactive mode also prompts before promoting a newer independent security update and persists an approved package name.
{ "overrides": { "alpha": "2.5.0" }, "pastoralist": { "bestCase": { "enabled": true, "userOwnedOverrides": ["alpha"] }, "appendix": { "[email protected]": { "ledger": { "addedDate": "2026-08-09T00:00:00.000Z" } } } }}userOwnedOverrides is the machine-readable ownership declaration. The active
override supplies the constrained version. The ledger addedDate is shown
as “user-owned since”, but the date alone does not establish ownership.
The built-in evaluator scans root packages and candidate-controlled packages.
It does not materialize lockfiles or resolve peer compatibility. A patched
version is not a guarantee of compatibility or freedom from other vulnerabilities. Projects that materialize lockfiles, solve peer constraints, or model
version-combination behavior can pass a whole-state bestCaseEvaluator through
the Node.js API.
| Option | Description |
|---|---|
--checkSecurity | Enable security vulnerability checking |
--forceSecurityRefactor | Automatically apply security fixes without prompting |
--securityProvider <provider> | Specify one or more security providers |
--securityProviderToken <token> | Provide an authentication token for one-off/local use |
--interactive | Use interactive mode to select fixes |
--hasWorkspaceSecurityChecks | Include workspace packages in the security scan |
--strict | Fail on provider, network, or API errors |
Set provider tokens with environment variables whenever possible:
GITHUB_TOKEN, SNYK_TOKEN, SOCKET_SECURITY_API_KEY, or SPEKTION_API_KEY.
securityProviderToken remains available for controlled local or generated
config, but do not commit real tokens to the repository.
Pastoralist npm releases are published from GitHub Actions with npm provenance. The release workflow also packs the npm tarball before publishing and creates a GitHub artifact attestation for that exact tarball.
You can inspect provenance on the npm package page and verify registry signatures from your own project:
npm audit signaturesThese checks prove where the package was built and which artifact was published. They do not prove the code is bug-free, so the project also runs CI, CodeQL, OpenSSF Scorecard, dependency update policy checks, and unit, integration, and e2e tests.
Free and requires no token.
The OSV database is a distributed vulnerability database for open source, created by Google and the open source community.
Requires authentication. The GitHub provider reads your repository's Dependabot alerts, including alerts for transitive dependencies.
The GitHub provider supports two authentication methods:
Option 1: GitHub CLI
If you have the GitHub CLI installed and authenticated, no additional setup is required:
# Install and authenticate gh CLIgh auth login # Run pastoralist with GitHub providerpastoralist --checkSecurity --securityProvider githubOption 2: Personal Access Token
If you don't have the GitHub CLI, you can provide a GitHub token:
repo scopeexport GITHUB_TOKEN="..."pastoralist --checkSecurity --securityProvider github --securityProviderToken "$GITHUB_TOKEN"When using the GitHub provider in CI workflows, you need to:
permissions: contents: read vulnerability-alerts: readIf permissions are insufficient, Pastoralist displays a warning and continues.
Runs the current package manager's audit command and converts the result into Pastoralist security alerts.
pastoralist --checkSecurity --securityProvider npmThis provider uses the package manager detected for the project: npm, Yarn, pnpm, or Bun.
The Snyk provider is experimental and may have breaking changes. Report issues at https://github.com/yowainwright/pastoralist/issues
Requires the Snyk CLI and API authentication token.
# Set your Snyk tokenexport SNYK_TOKEN="..." # Run with Snyk providerpastoralist --checkSecurity --securityProvider snykThe Socket provider is experimental and may have breaking changes. Report issues at https://github.com/yowainwright/pastoralist/issues
Requires the Socket CLI and API key.
# Set your Socket API keyexport SOCKET_SECURITY_API_KEY=your_key_here # Run with Socket providerpastoralist --checkSecurity --securityProvider socketThe Spektion provider is experimental and may have breaking changes. Report issues at https://github.com/yowainwright/pastoralist/issues
Requires a Spektion API key.
# Set your Spektion API keyexport SPEKTION_API_KEY=your_key_here # Run with Spektion providerpastoralist --checkSecurity --securityProvider spektionExpanded appendix entries have a ledger. When a security provider detects a fix,
Pastoralist adds CVE, severity, provider, and vulnerable-range metadata to that
ledger alongside the addedDate:
{ "[email protected]": { "dependents": { "my-app": "lodash@^4.17.0" }, "ledger": { "addedDate": "2026-05-30T00:00:00.000Z", "source": "security", "securityChecked": true, "securityProvider": "osv", "cves": ["CVE-2021-23337"], "cveDetails": [ { "cve": "CVE-2021-23337", "severity": "high", "patchedVersion": "4.17.21" } ], "severity": "high", "vulnerableRange": "<4.17.21", "patchedVersion": "4.17.21" } }}For packages with multiple CVEs, cveDetails records the severity and patched
version for each CVE when available. cves lists the unique CVE identifiers.
reason accepts a non-empty string or a typed project or best-case object.
A best-case reason links each dependency entry to the shared portfolio decision;
the fixed CVEs remain in the sibling cves field.
keepBy default, --remove-unused removes overrides whose dependents no longer
require them. For security overrides you want to retain, set keep on the
ledger:
{ "ledger": { "addedDate": "2026-05-30T00:00:00.000Z", "cves": ["CVE-2024-12345"], "keep": true }}For expiring keeps, use a KeepConstraint object:
{ "ledger": { "addedDate": "2026-05-30T00:00:00.000Z", "cves": ["CVE-2024-12345"], "keep": { "reason": "Waiting for upstream patch", "untilVersion": "4.18.0" } }}Once the root dependency reaches 4.18.0, the keep is expired and
--remove-unused can treat it as removable again.
package.json (and optionally workspace packages)--forceSecurityRefactor)--interactive)package.json overrides section with full CVE context in the ledgerhasWorkspaceSecurityChecks option--dry-run prevents project-file changes; providers may still write cachespackage.json--debug to see detailed logspackage.jsonexcludePackagesThis happens when the GitHub API can't access Dependabot alerts. To fix:
vulnerability-alerts: read permission to your workflowGITHUB_TOKEN is available in your workflowPastoralist will show specific guidance in the warning message.
--quiet --checkSecurity exits non-zero on findings. Add --strict to fail on
provider errors and --dry-run to preview project changes.
name: Security Checkon: [push, pull_request] jobs: security: runs-on: ubuntu-latest permissions: contents: read vulnerability-alerts: read # Required for GitHub provider steps: - uses: actions/checkout@v7 - uses: actions/[email protected] - run: npm install - run: npx pastoralist --dry-run --quiet --checkSecurity --securityProvider github --strict env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}For OSV provider (no permissions needed):
name: Security Checkon: [push, pull_request] jobs: security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: actions/[email protected] - run: npm install - run: npx pastoralist --dry-run --quiet --checkSecurity --strictsecurity: script: - npm install - npx pastoralist --dry-run --quiet --checkSecurity --strict only: - main - merge_requests# Check for vulnerabilities and display a report
pastoralist --checkSecurity --dry-run# Automatically apply security fixes
pastoralist --checkSecurity --forceSecurityRefactor# Choose which fixes to apply
pastoralist --checkSecurity --interactive# Include workspace packages in the scan
pastoralist --checkSecurity --hasWorkspaceSecurityChecks{
"pastoralist": {
"security": {
"enabled": false,
"provider": "osv",
"autoFix": false,
"interactive": false,
"hasWorkspaceSecurityChecks": false,
"severityThreshold": "medium",
"excludePackages": []
},
"bestCase": {
"enabled": false,
"userOwnedOverrides": []
}
}
}{
"pastoralist": {
"checkSecurity": true,
"bestCase": {
"enabled": true,
"riskAggregation": "both",
"search": {
"mode": "auto",
"exactStateLimit": 256,
"beamWidth": 16,
"maxEvaluations": 1000
}
}
}
}{
"overrides": {
"alpha": "2.5.0"
},
"pastoralist": {
"bestCase": {
"enabled": true,
"userOwnedOverrides": ["alpha"]
},
"appendix": {
"[email protected]": {
"ledger": {
"addedDate": "2026-08-09T00:00:00.000Z"
}
}
}
}
}npm audit signatures# Install and authenticate gh CLI
gh auth login
# Run pastoralist with GitHub provider
pastoralist --checkSecurity --securityProvider githubexport GITHUB_TOKEN="..."pastoralist --checkSecurity --securityProvider github --securityProviderToken "$GITHUB_TOKEN"permissions:
contents: read
vulnerability-alerts: readpastoralist --checkSecurity --securityProvider npm# Set your Snyk token
export SNYK_TOKEN="..."
# Run with Snyk provider
pastoralist --checkSecurity --securityProvider snyk# Set your Socket API key
export SOCKET_SECURITY_API_KEY=your_key_here
# Run with Socket provider
pastoralist --checkSecurity --securityProvider socket# Set your Spektion API key
export SPEKTION_API_KEY=your_key_here
# Run with Spektion provider
pastoralist --checkSecurity --securityProvider spektion{
"[email protected]": {
"dependents": { "my-app": "lodash@^4.17.0" },
"ledger": {
"addedDate": "2026-05-30T00:00:00.000Z",
"source": "security",
"securityChecked": true,
"securityProvider": "osv",
"cves": ["CVE-2021-23337"],
"cveDetails": [
{
"cve": "CVE-2021-23337",
"severity": "high",
"patchedVersion": "4.17.21"
}
],
"severity": "high",
"vulnerableRange": "<4.17.21",
"patchedVersion": "4.17.21"
}
}
}{
"ledger": {
"addedDate": "2026-05-30T00:00:00.000Z",
"cves": ["CVE-2024-12345"],
"keep": true
}
}{
"ledger": {
"addedDate": "2026-05-30T00:00:00.000Z",
"cves": ["CVE-2024-12345"],
"keep": {
"reason": "Waiting for upstream patch",
"untilVersion": "4.18.0"
}
}
}name: Security Check
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
permissions:
contents: read
vulnerability-alerts: read # Required for GitHub provider
steps:
- uses: actions/checkout@v7
- uses: actions/[email protected]
- run: npm install
- run: npx pastoralist --dry-run --quiet --checkSecurity --securityProvider github --strict
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}name: Security Check
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/[email protected]
- run: npm install
- run: npx pastoralist --dry-run --quiet --checkSecurity --strictsecurity:
script:
- npm install
- npx pastoralist --dry-run --quiet --checkSecurity --strict
only:
- main
- merge_requests