Skip to content

Package Scanner

The Package Scanner is a cross-platform CLI for scanning dependency manifests and uploading package inventory to ShieldedStack. It is useful for seeding existing repositories, scanning projects that do not restore through the proxy, and adding scheduled CI inventory checks.

Scanner uploads are sent to the package proxy at <proxy-url>/scans. For on-prem deployments, always configure the scanner with your deployed proxy URL.

Binaries are published for five platforms, always at the same URL for the current release:

Platform File
Linux (x64) package-scanner-linux-amd64
Linux (ARM64) package-scanner-linux-arm64
macOS (Intel) package-scanner-darwin-amd64
macOS (Apple Silicon) package-scanner-darwin-arm64
Windows (x64) package-scanner-windows-amd64.exe

Each is served from https://tools.shieldedstack.com/u/<file>, and SHA256 checksums for all five are published together at https://tools.shieldedstack.com/r/checksums.txt.

Verify the download before you run it. The steps below do that, substituting the file for your platform.

Terminal window
curl -LO https://tools.shieldedstack.com/u/package-scanner-linux-amd64
curl -L -o checksums.txt https://tools.shieldedstack.com/r/checksums.txt
grep package-scanner-linux-amd64 checksums.txt | sha256sum -c -

sha256sum prints OK when the file matches. If it does not, stop and do not run the binary.

Then put it on your PATH:

Terminal window
install -m 755 package-scanner-linux-amd64 ~/.local/bin/package-scanner

Use package-scanner-linux-arm64 on ARM64 machines.

Terminal window
curl -LO https://tools.shieldedstack.com/u/package-scanner-darwin-arm64
curl -L -o checksums.txt https://tools.shieldedstack.com/r/checksums.txt
grep package-scanner-darwin-arm64 checksums.txt | shasum -a 256 -c - \
&& install -m 755 package-scanner-darwin-arm64 ~/.local/bin/package-scanner

Use package-scanner-darwin-amd64 on Intel machines.

Terminal window
Invoke-WebRequest https://tools.shieldedstack.com/u/package-scanner-windows-amd64.exe -OutFile package-scanner.exe
(Get-FileHash .\package-scanner.exe -Algorithm SHA256).Hash.ToLower()

Compare the printed hash against the package-scanner-windows-amd64.exe line in https://tools.shieldedstack.com/r/checksums.txt, then move the executable somewhere on your PATH.

The download URLs always serve the current release, so an unpinned CI job picks up a new binary whenever one ships. Record the checksum you verified and check it on every run, as the GitHub Actions example does. The job then fails loudly when the binary changes rather than quietly running a different one.

<proxy-url> is the base URL of the package proxy, without a trailing slash. Pass it with --proxy-url <proxy-url>, or set SHIELDEDSTACK_PROXY_URL in the environment.

  • Multi-ecosystem support: npm, NuGet, pip, Go, Maven, Cargo, RubyGems, Dart.
  • Manifest-only scanning: Fast scans without dependency resolution.
  • Concurrent processing: Parallel manifest parsing.
  • Batch uploads: Efficient bulk submission to ShieldedStack.
  • Retry logic: Automatic retries with exponential backoff.
  • Rate limiting: Respects API rate limits.
  • Dry-run mode: Preview findings without uploading.
  • CI/CD ready: Non-interactive execution with clear exit codes.
  • package-lock.json v2/v3.
  • package.json fallback.
  • packages.lock.json.
  • *.csproj / *.fsproj using PackageReference.
  • packages.config.
  • requirements.txt.
  • Pipfile.lock.
  • poetry.lock.
  • go.mod.
  • pom.xml.
  • Cargo.lock.
  • Gemfile.lock.
  • pubspec.lock.
Terminal window
package-scanner --api-key YOUR_API_KEY --proxy-url <proxy-url> /path/to/project
Terminal window
export SHIELDEDSTACK_API_KEY=your_api_key
export SHIELDEDSTACK_PROXY_URL=<proxy-url>
package-scanner /path/to/project

With the default HTTP endpoint, this looks like:

Terminal window
export SHIELDEDSTACK_PROXY_URL=http://<host>:3003
package-scanner --api-key YOUR_API_KEY .

Preview findings without uploading:

Terminal window
package-scanner --dry-run --api-key YOUR_API_KEY --proxy-url <proxy-url> .
Terminal window
package-scanner --api-key YOUR_API_KEY --proxy-url <proxy-url> --exclude "test,examples" .
name: Scan Dependencies
on:
schedule:
- cron: '0 0 * * *'
push:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download Package Scanner
env:
SCANNER_SHA256: ${{ vars.SCANNER_SHA256 }}
run: |
curl -L https://tools.shieldedstack.com/u/package-scanner-linux-amd64 -o scanner
echo "${SCANNER_SHA256} scanner" | sha256sum -c -
chmod +x scanner
- name: Scan Dependencies
env:
SHIELDEDSTACK_API_KEY: ${{ secrets.SHIELDEDSTACK_API_KEY }}
SHIELDEDSTACK_PROXY_URL: ${{ vars.SHIELDEDSTACK_PROXY_URL }}
run: ./scanner --no-color .
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
curl -L https://tools.shieldedstack.com/u/package-scanner-linux-amd64 -o scanner
chmod +x scanner
displayName: 'Download Package Scanner'
- script: ./scanner --no-color .
env:
SHIELDEDSTACK_API_KEY: $(ShieldedStackApiKey)
SHIELDEDSTACK_PROXY_URL: $(ShieldedStackProxyUrl)
displayName: 'Scan Dependencies'
scan-dependencies:
image: alpine:latest
before_script:
- apk add --no-cache curl
- curl -L https://tools.shieldedstack.com/u/package-scanner-linux-amd64 -o scanner
- chmod +x scanner
script:
- ./scanner --no-color .
variables:
SHIELDEDSTACK_PROXY_URL: "<proxy-url>"
only:
- main

Store SHIELDEDSTACK_API_KEY as a protected CI secret. Store SHIELDEDSTACK_PROXY_URL as a variable or secret depending on your internal policy.

Flag Environment Variable Description
--api-key SHIELDEDSTACK_API_KEY ShieldedStack API key. Required for uploads.
--proxy-url SHIELDEDSTACK_PROXY_URL Package proxy base URL. Set this for on-prem deployments.
--include - Include glob patterns.
--exclude - Additional exclude patterns.
--dry-run - Print findings without uploading.
--output-json - Write results to JSON file.
--format - Output format: text or json.
--no-color - Disable colored output.
--concurrency - Worker pool size.

Do not rely on the scanner binary’s built-in proxy URL default for on-prem deployments. Set SHIELDEDSTACK_PROXY_URL or pass --proxy-url explicitly.

The scanner automatically excludes these directories:

  • node_modules
  • bin
  • obj
  • .venv / venv
  • .git
  • __pycache__
  • .pytest_cache
  • .mypy_cache
  • 0: Success; all packages uploaded.
  • 1: Upload errors such as network, auth, or rate-limit failures.
  • 2: Scan failures such as manifest parsing errors.

For monorepos with multiple projects or workspaces, run the scanner multiple times with different API keys and target directories:

Terminal window
# Frontend project
package-scanner --api-key FRONTEND_KEY --proxy-url <proxy-url> ./frontend
# Backend project
package-scanner --api-key BACKEND_KEY --proxy-url <proxy-url> ./backend

Verify your API key is correct, has not expired, and belongs to the workspace you expect:

Terminal window
package-scanner --dry-run --api-key YOUR_API_KEY --proxy-url <proxy-url> .

Then run without --dry-run to test upload authentication.

Confirm the active proxy URL:

Terminal window
printf '%s\n' "$SHIELDEDSTACK_PROXY_URL"

The scanner posts inventory to <proxy-url>/scans.

If you hit rate limits with 429 responses, the scanner automatically retries with backoff. Current limit: 5,000 packages/hour per API key.

Use JSON output to see which manifests fail to parse:

Terminal window
package-scanner --format json --api-key YOUR_API_KEY --proxy-url <proxy-url> . 2>&1 | tee scan.log