Scan npm dependencies for malicious code using the Manticore behavioral analysis backend.
- A Manticore account at tazarsec.dev. The GitHub Action authenticates via short-lived GitHub OIDC tokens by default, no long-lived API key needed. The CLI supports both OIDC and API-key auth.
- A GitHub-hosted or self-hosted runner on Linux, macOS, or Windows (amd64 or arm64).
- An npm project with a
package.jsonand/orpackage-lock.jsonchecked into the repository.
Two composite actions are published from this repository:
| Action | Purpose |
|---|---|
TazarSec/ManticoreScanner@v1 |
One-shot scan against your committed lockfile. Reports findings, optionally posts a PR comment, and can fail the job on suspicious packages. |
TazarSec/ManticoreScanner/setup@v1 |
Installs the manticore CLI on the runner PATH so you can invoke manticore scan or manticore exec from your own pipeline steps. |
Pin by full commit SHA. Manticore uses immutable releases, but commit hash pinning is more robust and is the format GitHub recommends for third-party actions:
- uses: TazarSec/ManticoreScanner@<full-commit-sha> # v1.2.3The floating @v1 and lightweight @v1.2.3 tag pins are also supported for convenience, but SHA pinning is the recommended option when hardening your supply chain.
Drop this into .github/workflows/manticore.yml to scan every push and pull request:
on: [push, pull_request]
permissions:
contents: read
id-token: write
jobs:
manticore:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #6.0.2
- uses: TazarSec/ManticoreScanner@v1The action auto-detects your package-lock.json (or package.json), authenticates with a freshly-minted GitHub OIDC token, fails the job on any non-zero suspicion score, and prints a results table to the job log. See the scan action section below to enable PR comments, raise the fail threshold, emit SARIF, and more.
Runs manticore scan against your lockfile and reports the results. Use this when you want a turnkey "open a PR, get findings on the PR" workflow.
permissions:
contents: read
id-token: write
pull-requests: write
jobs:
manticore:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #6.0.2
- uses: TazarSec/ManticoreScanner@v1
with:
fail-on: 50
vcs-comment: truePRs from forks: the default
GITHUB_TOKENis read-only onpull_requestevents triggered by forked repositories, sovcs-comment: truewill fail to post (the scan itself still runs and reports findings in the job output). If you need PR comments on fork PRs, switch the workflow trigger topull_request_target, but only after you've audited the security implications, since that trigger runs with the base repository's secrets.
| Input | Description | Default |
|---|---|---|
auth-mode |
Authentication mode: github-oidc (default) or api-key. github-oidc requires the workflow to grant permissions: id-token: write. |
github-oidc |
api-key |
Manticore API key. Required when auth-mode: api-key; ignored otherwise. |
|
api-url |
API base URL. | https://tazarsec.dev |
file |
Path to package.json / package-lock.json. |
auto-detected in working-directory |
format |
Output format: table, json, sarif. |
table |
output |
Write results to this path instead of stdout. | stdout |
fail-on |
Fail the job if any suspicion score is at or above this threshold. Pass a higher number to gate only on stronger signals. | 1 (any non-zero score fails) |
ignore-list |
Path to a file listing packages to skip — see Ignore specific packages. | none |
http-timeout |
Per-request HTTP timeout in seconds. | 120 |
timeout |
Polling timeout in seconds — how long to wait for backend results before erroring or continuing per on-error. |
300 |
on-error |
Behavior on backend errors or polling deadline exceeded with pending items: fail (exit non-zero) or continue (exit 0). |
fail |
production |
Set to true to skip devDependencies. |
false |
vcs-comment |
Set to true to post a PR comment with findings. |
false |
include-transitive |
Set to true to submit transitive deps — see Transitive dependencies. |
false |
insecure |
Allow plaintext http:// API URLs. TLS is required when false. |
false |
working-directory |
Directory to run the scan from. | . |
version |
Pin a specific release tag (e.g. v1.2.3). |
the ref the action was invoked with (e.g. v1) |
Installs the CLI on PATH and stops there. Use this when you want to drive manticore directly to gate npm install at execution time, run scans on dynamically-resolved lockfiles, emit SARIF for code scanning, or chain it with other steps.
manticore exec wraps a package manager install command. It first resolves the dependency tree to a lockfile without executing install scripts, scans every package, and only invokes the real install if the scan passes. This blocks malicious payloads on the runner before they get a chance to run.
permissions:
contents: read
id-token: write
jobs:
build:
runs-on: ubuntu-latest
env:
MANTICORE_AUTH_MODE: github-oidc
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #6.0.2
- uses: TazarSec/ManticoreScanner/setup@v1
- run: manticore exec --fail-on 50 -- npm ci
- run: npm run buildSupported package managers: npm. Supported subcommands: install, ci, and install <pkg>.
permissions:
contents: read
id-token: write
jobs:
scan:
runs-on: ubuntu-latest
env:
MANTICORE_AUTH_MODE: github-oidc
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #6.0.2
- uses: TazarSec/ManticoreScanner/setup@v1
- run: manticore scan --format sarif --output manticore.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: manticore.sarifConfigure runtime behavior via flags or MANTICORE_* environment variables. See CLI below.
| Input | Description | Default |
|---|---|---|
version |
Pin a specific release tag (e.g. v1.2.3). |
the ref the action was invoked with (e.g. v1) |
go install github.com/TazarSec/ManticoreScanner/cmd/manticore@latestOr build from source:
git clone https://github.com/TazarSec/ManticoreScanner.git
cd ManticoreScanner
go build -o manticore ./cmd/manticorePre-built release binaries (manticore-<os>-<arch>) and a Docker image are also published. See Verifying release artifacts and Docker.
Parses an npm lockfile (or package.json) and submits dependencies to the backend for behavioral analysis.
The CLI supports two auth modes, selected with --auth-mode or MANTICORE_AUTH_MODE:
api-key(default) - long-lived key passed via--api-keyorMANTICORE_API_KEY. Use this for local runs and any CI other than GitHub Actions.github-oidc- mint a short-lived JWT from GitHub Actions' OIDC provider (audiencetazarsec.dev). Requires the workflow to grantpermissions: id-token: write; the CLI readsACTIONS_ID_TOKEN_REQUEST_URLandACTIONS_ID_TOKEN_REQUEST_TOKENautomatically. The wrapper GitHub Action sets this mode by default. You only need to pass--auth-mode github-oidcwhen invoking the CLI directly inside a workflow.
If MANTICORE_API_KEY is set while --auth-mode=github-oidc is selected, the CLI ignores the key and prints a warning.
Auto-detect package-lock.json or package.json in the current directory:
manticore scan --api-key YOUR_API_KEYmanticore scan --api-key YOUR_API_KEY --file path/to/package-lock.json# Human-readable table (default)
manticore scan --api-key YOUR_API_KEY --format table
# JSON
manticore scan --api-key YOUR_API_KEY --format json
# SARIF (for GitHub Code Scanning)
manticore scan --api-key YOUR_API_KEY --format sarif --output results.sarifBy default the scan exits non-zero if any package has a suspicion score of 1 or higher (i.e., any non-zero finding). Pass --fail-on N to raise the threshold and only fail on stronger signals:
manticore scan --api-key YOUR_API_KEY --fail-on 50The default threshold can also be overridden via the MANTICORE_FAILURE_THRESHOLD environment variable.
manticore scan --api-key YOUR_API_KEY --productionBy default the scanner submits only direct dependencies (the entries in your package.json dependencies / devDependencies). The backend's behavioral analysis already executes transitive code when it installs each direct package, so most "live payload" supply-chain attacks are caught indirectly.
If you want every package in the resolved tree submitted by name, opt in:
manticore scan --api-key YOUR_API_KEY --include-transitiveTrade-off: this can multiply your scan volume by 10–100× on a typical Node project. Leave it off unless you specifically need static-signal coverage on transitives.
Pass a file with one entry per line. Each entry must pin a specific release, either name@version or a lockfile integrity hash (e.g. sha512-...). Bare package names are rejected so an ignore never silently covers a future malicious version. Blank lines and lines starting with # are ignored. Matching packages are skipped before submission, so they don't count against your scan quota.
Hash matching reads the integrity field from package-lock.json; entries in package.json have no hash and can only be ignored by name@version.
manticore scan --api-key YOUR_API_KEY --ignore-list .manticoreignore# .manticoreignore
[email protected]
@scope/[email protected]
sha512-oRjE9PZkgGr/QJtKqz5IngnFFiLk5xQxQ4y+9k4dZB5RZ2yMJZ8R3pYV+Q0WQ1l7xq4j6+UqQc9Yj3o/4G0sUQ==
By default no ignore list is used.
When running in GitHub Actions, post a comment with suspicious packages to the PR:
manticore scan --api-key YOUR_API_KEY --vcs-commentWraps a package manager install command. Resolves the dependency tree to a lockfile without running install scripts, scans every package, and only proceeds with the real install if the scan passes.
manticore exec -- npm ci
manticore exec -- npm install
manticore exec -- npm install lodash
manticore exec --fail-on 50 -- npm install
manticore exec --ignore-list .manticoreignore -- npm ci
manticore exec --on-error continue -- npm ciSupported package managers: npm.
exec shares the same --fail-on default as scan (1 — any non-zero suspicion score blocks the install) and respects MANTICORE_FAILURE_THRESHOLD the same way. Pass --fail-on N (or set the env var) to gate only on stronger signals, e.g. --fail-on 50 to block on moderate findings or --fail-on 70 to block only on strong ones. Use --ignore-list to waive specific pinned packages (same format as scan). Use --on-error continue to proceed with the install if the backend is unreachable or the polling deadline is exceeded with packages still pending — this trades the security gate for availability.
Every variable below is optional and overridden by the equivalent CLI flag when both are set.
| Variable | Description | Default |
|---|---|---|
MANTICORE_AUTH_MODE |
Authentication mode: api-key or github-oidc. |
api-key |
MANTICORE_API_KEY |
API key (alternative to --api-key). Used when MANTICORE_AUTH_MODE=api-key. |
— |
MANTICORE_API_URL |
API base URL. | https://tazarsec.dev |
MANTICORE_TIMEOUT |
Polling timeout in seconds. | 300 |
MANTICORE_HTTP_TIMEOUT |
Per-request HTTP timeout in seconds. | 120 |
MANTICORE_ON_ERROR |
Behavior on backend errors or polling deadline exceeded with pending items: fail or continue. |
fail |
MANTICORE_FORMAT |
Output format: table, json, sarif. |
table |
MANTICORE_FAILURE_THRESHOLD |
Default --fail-on threshold when not passed explicitly. |
1 (any non-zero score fails) |
MANTICORE_IGNORE_LIST |
Path to an ignore-list file (alternative to --ignore-list). |
none |
MANTICORE_INCLUDE_TRANSITIVE |
Set to true to submit transitive deps. |
false (direct deps only) |
MANTICORE_INSECURE |
Set to true to allow plaintext http:// API URLs. |
false (HTTPS required) |
Multi-arch images (linux/amd64, linux/arm64) are published to GHCR on every release. Tags: vX.Y.Z (immutable), vX (latest release in the major line), and latest.
docker run --rm \
-v $(pwd):/workspace \
-w /workspace \
ghcr.io/tazarsec/manticorescanner:latest \
scan --api-key YOUR_API_KEYRelease images are signed by digest with cosign keyless (Sigstore + GitHub OIDC) and have a SLSA build-provenance attestation pushed to the registry.
IMAGE=ghcr.io/tazarsec/manticorescanner:v1.2.3
# Cosign keyless signature
cosign verify "${IMAGE}" \
--certificate-identity-regexp '^https://github.com/TazarSec/ManticoreScanner/\.github/workflows/release\.yml@refs/tags/v.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
# SLSA build provenance
gh attestation verify "oci://${IMAGE}" --repo TazarSec/ManticoreScannerFor reproducible pulls pin by digest instead of tag:
docker pull ghcr.io/tazarsec/manticorescanner@sha256:<digest>Every release publishes checksums.txt with a keyless signature plus a SLSA build provenance attestation per binary:
- Keyless signature (
checksums.txt.sig/checksums.txt.pem) produced automatically by the release workflow using cosign + Sigstore Fulcio + GitHub OIDC, transparency-logged in Rekor. - Build provenance attestations for every
manticore-*binary via GitHub's attest-build-provenance.
Verify with either — or both — of them:
# 1. Keyless (Sigstore/OIDC)
cosign verify-blob \
--certificate checksums.txt.pem \
--signature checksums.txt.sig \
--certificate-identity-regexp '^https://github.com/TazarSec/ManticoreScanner/\.github/workflows/release\.yml@refs/tags/v.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
checksums.txt
# 2. SLSA build provenance
gh attestation verify manticore-linux-amd64 --repo TazarSec/ManticoreScanner
# Then validate the binary itself against the verified manifest
sha256sum --check --ignore-missing checksums.txtLicensed under the Apache License, Version 2.0 (SPDX: Apache-2.0). See NOTICE for attribution.