DocsCLI

CLI

Developer-first command line interface for scans, batch runs, and live monitoring.

Malware Scanner CLI

A command-line tool for scanning npm packages for malicious code patterns, typosquatting, and security vulnerabilities.

Installation

# Install globally
npm install -g malwarescanner

# Or run directly with bun
bun run src/cli/scanner.ts

Quick Start

# Scan a package from npm
malware-scanner scan lodash

# Scan multiple packages from a file
malware-scanner batch -f packages.txt

# Monitor npm registry in real-time
malware-scanner live

Commands

scan - Scan a single package

Scans an npm package for malware patterns, suspicious code, and security issues.

# Scan latest version from npm
malware-scanner scan lodash

# Scan specific version
malware-scanner scan lodash@4.17.21

# Scan scoped package
malware-scanner scan @types/node

# Scan local directory
malware-scanner scan --local ./my-package

# Scan local tarball
malware-scanner scan --tarball ./package.tgz

# Pipe tarball from stdin
cat package.tgz | malware-scanner scan --stdin

# Output as JSON
malware-scanner scan lodash --json

# Save results to file
malware-scanner scan lodash -o results.json --json

Options:

OptionDescription
-j, --jsonOutput results as JSON
-q, --quietSuppress progress output
-l, --localScan a local directory
-t, --tarballScan a local tarball file (.tgz)
--stdinRead tarball from stdin (max 100MB, 30s timeout)
-o, --output <file>Write results to file
--timeout <seconds>Scan timeout in seconds (default: 300)

Exit Codes:

  • 0 - Package is clean
  • 1 - Warnings detected or scan error
  • 2 - Critical threats detected

batch - Scan multiple packages

Scans multiple packages from a file or stdin with concurrency control and rate limiting.

# Scan packages from file
malware-scanner batch -f packages.txt

# Scan from stdin
echo -e "lodash\nreact\nexpress" | malware-scanner batch

# Save results to JSON file
malware-scanner batch -f packages.txt -o results.json

# Output as streaming NDJSON
malware-scanner batch -f packages.txt --json

# Adjust concurrency (default: 3, max: 10)
malware-scanner batch -f packages.txt -c 5

# Stop on first critical threat
malware-scanner batch -f packages.txt --fail-fast

Package File Format:

# Comments start with hash
lodash@4.17.21
@types/node
react
express@^4.18.0

Options:

OptionDescription
-f, --file <path>Input file with package list (one per line)
-o, --output <path>Output file for results (JSON format)
-j, --jsonOutput results as NDJSON to stdout
-q, --quietSuppress progress output
-c, --concurrency <n>Number of concurrent scans (1-10, default: 3)
--fail-fastStop on first critical threat
--timeout <seconds>Scan timeout per package (default: 300)

Rate Limiting: The batch command includes automatic rate limiting:

  • 100ms delay between batches
  • Exponential backoff on 429 errors (1s → 2s → 4s → ... up to 30s)
  • Up to 3 retries per package on rate limit errors

live - Monitor npm registry

Monitors the npm registry changes feed in real-time and scans new package publications.

# Start monitoring with defaults
malware-scanner live

# Only report critical threats
malware-scanner live -t critical

# Output as JSON events (for piping to other tools)
malware-scanner live --json

# Skip scoped packages
malware-scanner live --skip-scoped

# Adjust queue depth for backpressure control
malware-scanner live -m 500

Options:

OptionDescription
-t, --threshold <level>Minimum threat level to report (info|warning|critical)
-m, --max-queue <n>Maximum queue depth before backpressure (default: 1000)
-s, --skip-scopedSkip scoped packages (@org/name)
-j, --jsonOutput events as JSON (one per line)
-q, --quietSuppress all output except threats

Requirements:

  • Redis server running on localhost:6379 (or set REDIS_URL env var)

Example Redis setup:

docker run -d -p 6379:6379 redis

config - Manage configuration

# Create a sample config file
malware-scanner config init

# Show current configuration
malware-scanner config show

# Show config as JSON
malware-scanner config show --json

# Show path to active config file
malware-scanner config path

completion - Shell completions

Generate shell completion scripts for enhanced command-line experience.

# Bash
malware-scanner completion bash >> ~/.bashrc

# Zsh
malware-scanner completion zsh >> ~/.zshrc

# Fish
malware-scanner completion fish > ~/.config/fish/completions/malware-scanner.fish

Configuration

The CLI supports multiple configuration sources (in order of precedence):

  1. CLI arguments (highest priority)
  2. Environment variables
  3. Configuration files
  4. Defaults (lowest priority)

Configuration Files

Create a configuration file in any of these formats:

  • .malwarescannerrc.json
  • .malwarescannerrc.yaml / .malwarescannerrc.yml
  • .malwarescannerrc.js / .malwarescannerrc.cjs / .malwarescannerrc.mjs
  • malwarescanner.config.js
  • package.json (under "malwarescanner" key)

Example .malwarescannerrc.json:

{
  "threshold": "warning",
  "format": "console",
  "timeout": 300,
  "concurrency": 3,
  "maxQueueDepth": 1000,
  "skipScoped": false,
  "plugins": {
    "installScripts": true,
    "networkAccess": true,
    "typosquat": true,
    "obfuscation": true,
    "llmAnalysis": false
  },
  "thresholds": {
    "obfuscationEntropy": 5.5,
    "typosquatLevenshtein": 2
  }
}

Environment Variables

VariableDescription
MALWARE_SCANNER_THRESHOLDDefault threat level threshold (info|warning|critical)
MALWARE_SCANNER_FORMATOutput format (console|json)
MALWARE_SCANNER_TIMEOUTDefault timeout in seconds
MALWARE_SCANNER_CONCURRENCYDefault concurrency (1-10)
REDIS_URLRedis connection URL for live monitoring
ANTHROPIC_API_KEYAPI key for LLM-based analysis
NO_COLORDisable colored output (any value)
FORCE_COLORForce color level (0-3)

Global Options

These options work with all commands:

OptionDescription
--no-colorDisable colored output
--verboseEnable verbose output for debugging
-h, --helpShow help
-V, --versionShow version

Output Formats

Console (Default)

Human-readable colored output with threat indicators:

Scan Results: lodash@4.17.21
──────────────────────────────────────────────────
  ✓ No issues detected

Threat Level: CLEAN
Threat Score: 0/100
Scan Duration: 1234ms

JSON

Structured output for automation:

malware-scanner scan lodash --json
{
  "packageName": "lodash",
  "version": "4.17.21",
  "threatLevel": "clean",
  "threatScore": 0,
  "alerts": [],
  "scanDurationMs": 1234,
  "scannedAt": "2024-01-15T10:30:00.000Z"
}

NDJSON (Batch)

Newline-delimited JSON for streaming:

malware-scanner batch -f packages.txt --json
{"type":"scan_result","packageSpec":"lodash@4.17.21","threatLevel":"clean",...}
{"type":"scan_result","packageSpec":"react@18.2.0","threatLevel":"clean",...}
{"type":"scan_error","packageSpec":"nonexistent-pkg","error":"Package not found"}

Detection Capabilities

The scanner checks for:

  • Install Scripts: Suspicious preinstall, postinstall, prepare hooks
  • Network Access: Code that makes HTTP/HTTPS requests, DNS lookups, or socket connections
  • Typosquatting: Package names similar to popular packages (Levenshtein distance, keyboard proximity)
  • Obfuscation: High entropy code, base64-encoded payloads, eval usage
  • Sensitive File Access: Attempts to read .npmrc, .ssh, credentials, etc.
  • Environment Access: Code accessing sensitive environment variables
  • Child Process: Spawning shells or executing commands

Examples

CI/CD Integration

# GitHub Actions example
- name: Scan dependencies
  run: |
    npm install -g malwarescanner
    malware-scanner batch -f package-lock.json --fail-fast
    if [ $? -eq 2 ]; then
      echo "Critical threats detected!"
      exit 1
    fi

Scripting with JSON

# Get threat level programmatically
threat_level=$(malware-scanner scan lodash --json | jq -r '.threatLevel')
if [ "$threat_level" = "critical" ]; then
  echo "Do not install this package!"
fi

Verbose Debugging

# See detailed scan progress
malware-scanner scan lodash --verbose

Output:

[verbose] Loading configuration...
[verbose] Config loaded: timeout=300s, threshold=warning
[verbose] Creating detection service with timeout: 300s
[verbose] Scanning npm package: lodash@latest
[verbose] Fetching package from npm registry...
[verbose] Scan complete: 0 alerts, threat level: clean, duration: 1234ms
[verbose] Output written to stdout

Troubleshooting

"No data piped to stdin"

When using --stdin, make sure to pipe data:

cat package.tgz | malware-scanner scan --stdin

"Redis connection refused" (live command)

Start Redis before using the live monitor:

docker run -d -p 6379:6379 redis
# or
brew services start redis

Rate limiting in batch mode

The batch command handles rate limiting automatically. If you see many retries, consider:

  • Reducing concurrency: -c 1
  • Adding delays between runs
  • Using a caching npm registry proxy

Large packages timing out

Increase the timeout:

malware-scanner scan large-package --timeout 600

License

MIT