Security Vulnerability Detection
Detect vulnerabilities and select lowest-risk dependency portfolios
Detect vulnerabilities and select lowest-risk dependency portfolios
Pastoralist can check dependencies against security providers and connect fixes to the same appendix used for override tracking.
Security checks scan your dependencies, report vulnerable packages, and can suggest or apply package manager overrides when a safe version is available. The appendix keeps the CVE, provider, severity, patched version, and reason with the override.
# Check for vulnerabilities and display a report
pastoralist --checkSecurity
# Automatically apply security fixes
pastoralist --checkSecurity --forceSecurityRefactor
# Choose which fixes to apply
pastoralist --checkSecurity --interactive
# Include workspace packages in the scan
pastoralist --checkSecurity --hasWorkspaceSecurityChecks
You 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 displayed
as the human-facing “user-owned since” signal, but does not establish ownership
by itself.
The built-in evaluator scans all root packages and candidate-controlled
packages. Projects that materialize lockfiles, solve peer constraints, or model
version-combination behavior can pass a whole-state bestCaseEvaluator through
the Node.js API.
Package contributes a set of candidate versions . The complete search space is the Cartesian product of those sets:
Let be the resolved policy, where each is an objective and is the risk-aggregation mode. Each objective produces a score block , and the blocks are concatenated in policy order:
The default blocks represent known-exploited vulnerabilities, critical
vulnerabilities, high vulnerabilities, summed EPSS, package exposures,
incompatibilities, changed packages, and oldness. With riskAggregation: "both",
security blocks contain both unique-advisory and package-exposure values.
Pastoralist minimizes the vector lexicographically:
For each selected dependency , the ledger reason stores the shared decision provenance:
The reason is per dependency, while the decision ID connects every dependency
selected in the same portfolio. CVE identifiers remain in the sibling cves
field rather than being duplicated in .
| 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 signatures
These 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 a token but provides more in-depth security awareness, including transitive dependencies.
The GitHub provider uses Dependabot alerts to check for vulnerabilities. This provider queries GitHub's Dependabot API for your repository.
The GitHub provider supports two authentication methods:
Option 1: GitHub CLI (Recommended)
If you have the GitHub CLI installed and authenticated, no additional setup is required:
# Install and authenticate gh CLI
gh auth login
# Run pastoralist with GitHub provider
pastoralist --checkSecurity --securityProvider github
Option 2: Personal Access Token
If you don't have the GitHub CLI, you can provide a GitHub token:
repo scopeexport GITHUB_TOKEN=your_token_here
pastoralist --checkSecurity --securityProvider github --securityProviderToken your_token_here
When using the GitHub provider in CI workflows, you need to:
permissions:
contents: read
vulnerability-alerts: read
If permissions are insufficient, Pastoralist will display a warning with guidance and continue (your workflow won't fail).
Runs the current package manager's audit command and converts the result into Pastoralist security alerts.
pastoralist --checkSecurity --securityProvider npm
This provider uses the package manager detected for the project: npm, Yarn, pnpm, or Bun.
:::caution[Experimental] 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 token
export SNYK_TOKEN=your_token_here
# Run with Snyk provider
pastoralist --checkSecurity --securityProvider snyk
:::caution[Experimental] The 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 key
export SOCKET_SECURITY_API_KEY=your_key_here
# Run with Socket provider
pastoralist --checkSecurity --securityProvider socket
:::caution[Experimental] The 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 key
export SPEKTION_API_KEY=your_key_here
# Run with Spektion provider
pastoralist --checkSecurity --securityProvider spektion
Every appendix entry has 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"
}
}
}
Multiple CVEs from the same package are aggregated — cveDetails gives per-CVE granularity (severity and patched version per identifier), while cves is the deduplicated flat list for quick reference.
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 will remove overrides whose dependents no longer require them. For security overrides you want to retain regardless, 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 considered expired and --remove-unused will treat it as removable again.
package.json (and optionally workspace packages)--forceSecurityRefactor)--interactive)package.json overrides section with full CVE context in the ledgerpastoralist checking for security vulnerabilities...
Security Check Report
==================================================
Found 3 vulnerable package(s):
[email protected]
Prototype Pollution
CVE: CVE-2021-23337
Fix available: 4.17.21
https://osv.dev/vulnerability/GHSA-35jh-r3h4-6jhm
[email protected]
Prototype Pollution
CVE: CVE-2021-44906
Fix available: 1.2.6
https://osv.dev/vulnerability/GHSA-xvch-5gv4-984h
Generated 2 override(s):
"lodash": "4.17.21" // Security fix: Prototype Pollution (high)
"minimist": "1.2.6" // Security fix: Prototype Pollution (medium)
:::caution[Performance Impact]
hasWorkspaceSecurityChecks option:::note[Current Limitations]
--debug to see detailed logsexcludePackagesThis 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.
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 --checkSecurity --securityProvider github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
For OSV provider (no permissions needed):
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 --checkSecurity
security:
script:
- npm install
- npx pastoralist --checkSecurity
only:
- main
- merge_requests
# Check for vulnerabilities and display a report
pastoralist --checkSecurity
# 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 github
export GITHUB_TOKEN=your_token_here
pastoralist --checkSecurity --securityProvider github --securityProviderToken your_token_here
permissions:
contents: read
vulnerability-alerts: read
pastoralist --checkSecurity --securityProvider npm
# Set your Snyk token
export SNYK_TOKEN=your_token_here
# 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"
}
}
}
pastoralist checking for security vulnerabilities...
Security Check Report
==================================================
Found 3 vulnerable package(s):
[email protected]
Prototype Pollution
CVE: CVE-2021-23337
Fix available: 4.17.21
https://osv.dev/vulnerability/GHSA-35jh-r3h4-6jhm
[email protected]
Prototype Pollution
CVE: CVE-2021-44906
Fix available: 1.2.6
https://osv.dev/vulnerability/GHSA-xvch-5gv4-984h
Generated 2 override(s):
"lodash": "4.17.21" // Security fix: Prototype Pollution (high)
"minimist": "1.2.6" // Security fix: Prototype Pollution (medium)
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 --checkSecurity --securityProvider github
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 --checkSecurity
security:
script:
- npm install
- npx pastoralist --checkSecurity
only:
- main
- merge_requests