npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ship-risk

v1.0.0

Published

AI-Code Readiness Scanner - Spot the gap between 'AI says it's done' and production-ready code with explainable risk scoring.

Downloads

22

Readme

ship-risk

AI-Code Readiness Scanner — Spot the exact gap between "AI says it's done" and production-ready code with NIRNAY-style explainable risk scoring.

npm version license CI tests

npx ship-risk scan

AI code generators (Cursor, Claude, Copilot, ChatGPT) write syntactically correct code that looks complete, but systematically omit production guardrails: auth checks on sensitive endpoints, input validation, try/catch around async boundaries, rate limiting, and actual assertions in generated tests.

ship-risk is a sibling tool to predeploy-check, focused on code risk and readiness rather than deployment host configuration. It parses your JavaScript/TypeScript code using AST analysis and computes a transparent readiness score (0–100).


Example Terminal Output

╔═══════════════════════════════════════════════════════════════════╗
║          ship-risk · AI-Code Readiness & Quality Scanner        ║
╚═══════════════════════════════════════════════════════════════════╝

  Target: ./my-express-api   Files: 24   Time: 0.18s

  Overall Readiness Score: 62/100  [████████████░░░░░░░░]  HUMAN REVIEW REQUIRED
  CI Threshold: ✖ Failed CI gate (min: 70, current: 62)

  ───────────────────────────────────────────────────────────────────
  EXPLAINABLE RISK BREAKDOWN (NIRNAY-Traceable SHAP Attribution)
  ───────────────────────────────────────────────────────────────────

  ● Secrets & Credentials                      90/100 [███████████░]  ⚠ 1 finding (-15 pts)
     CRITICAL  routes/billing.js:12 (-15 pts)
       Hardcoded secret assigned to variable "stripeSecret".
       ↳ Fix: Move secret into an environment variable and load it via process.env.

  ● Auth & Access Control                      40/100 [█████░░░░░░░]  ⚠ 2 findings (-35 pts)
     CRITICAL  routes/admin.js:5 (-22.5 pts)
       Sensitive Express route "GET /api/admin/users" has no auth middleware.
       ↳ Fix: Enforce authentication and session validation before processing sensitive user/billing data.

     HIGH  routes/admin.js:5 (-15 pts)
       Admin endpoint "GET /api/admin/users" does not enforce role or permission checks.
       ↳ Fix: Verify user roles (e.g., req.user.role === "admin") before executing.

  ● Input Validation & Sanitization            70/100 [████████░░░░]  ⚠ 2 findings (-23 pts)
     CRITICAL  routes/admin.js:7 (-22.5 pts)
       Raw SQL query constructed using string concatenation '+' (SQL injection risk).
       ↳ Fix: Use parameterized queries, prepared statements ($1, ?), or an ORM/query builder.

  ● Error Handling & Async Boundaries          80/100 [██████████░░]  ⚠ 1 finding (-9 pts)
     MED  routes/billing.js:14 (-4.2 pts)
       Async route handler lacks try/catch block. Unhandled rejections will crash server.
       ↳ Fix: Wrap handler logic in try/catch or wrap the route with express-async-handler.

  ● Test Suite & Assertion Coverage            30/100 [████░░░░░░░░]  ⚠ 2 findings (-10 pts)
     HIGH  test/dummy.test.js:1 (-6 pts)
       Test file has 0 assertions (expect/assert). Stubs provide false confidence in AI code.
       ↳ Fix: Add concrete expect() or assert statements verifying actual behavior.

  ● Reliability & Security Config Hygiene      85/100 [██████████░░]  ⚠ 2 findings (-10 pts)
     LOW  server.js:11 (-0.8 pts)
       Leftover `console.log()` detected in production code path.
       ↳ Fix: Replace console.log with a structured logger (pino, winston).

  ───────────────────────────────────────────────────────────────────
  Total Findings: 10   Address the fixes above before deploying to production.

Core Detection Categories

Every point deducted is traceable to a specific rule that fired — inspired by the explainability mechanics of the NIRNAY risk-attribution architecture.

| Category | Default Weight | Key Rules Detected | |---|:---:|---| | Secrets & credentials | 25% | • Hardcoded tokens & API keys (OpenAI, AWS, Stripe, GitHub, Slack, DB URI)• Shannon entropy check for high-entropy secrets• Direct .env imports instead of process.env• Committed .env files with real keys missing from .gitignore | | Auth & access control | 25% | • Express & Next.js API routes lacking auth middleware• Unprotected sensitive endpoints (/user, /admin, /billing, /payment)• Privileged mutations missing role/permission checks | | Input validation | 20% | • Direct req.body/req.query/req.params access without Zod/Joi/Yup• Raw SQL string concatenation or template literal injection• Unsanitized input passed to eval, exec, or dangerouslySetInnerHTML | | Error handling | 10% | • Async Express route handlers without try/catch or asyncHandler• Floating unhandled promises without await or .catch()• Empty catch blocks swallowing errors silently | | Testing | 10% | • Production source files with no matching test file• AI-generated stub test files with 0 assertions (expect())• Overall test-to-source file ratio (< 30%) | | Reliability & hygiene | 10% | • Leftover console.log() in production server routes• Missing rate limiting middleware (express-rate-limit, @upstash/ratelimit)• CORS configured with wildcard origin (*)• Missing security headers (helmet) |


Quick Start

Run directly with npx (zero install)

# Scan the current directory
npx ship-risk scan

# Scan a specific directory
npx ship-risk scan ./apps/api

# Run machine-readable JSON output (ideal for CI)
npx ship-risk scan --json

# Filter scan to a single category
npx ship-risk scan --category=secrets
npx ship-risk scan --category=auth

# Gate a build in CI/CD (exits non-zero if readiness score < 70)
npx ship-risk scan --min-score=70

Install globally or in your devDependencies

# Global
npm install -g ship-risk

# Local dev dependency
npm install --save-dev ship-risk

Machine-Readable JSON Mode (--json)

Pipe directly into jq, Datadog, or your custom CI pipeline:

npx ship-risk scan --json
{
  "score": 62,
  "passed": false,
  "minScoreThreshold": 70,
  "totalFindings": 10,
  "totalFilesScanned": 24,
  "targetPath": "/home/runner/work/my-app",
  "durationMs": 182,
  "timestamp": "2026-08-29T15:20:00.000Z",
  "categories": {
    "secrets": {
      "score": 90,
      "weight": 25,
      "deduction": 15,
      "findings": [
        {
          "file": "routes/billing.js",
          "line": 12,
          "rule": "hardcoded-secret",
          "category": "secrets",
          "severity": "critical",
          "deduction": 15,
          "message": "Hardcoded secret assigned to variable \"stripeSecret\".",
          "fix": "Move secret into an environment variable and load it via process.env."
        }
      ]
    },
    "auth": {
      "score": 40,
      "weight": 25,
      "deduction": 37.5,
      "findings": [
        {
          "file": "routes/admin.js",
          "line": 5,
          "rule": "unprotected-sensitive-route",
          "category": "auth",
          "severity": "critical",
          "deduction": 22.5,
          "message": "Sensitive Express route \"GET /api/admin/users\" has no auth middleware.",
          "fix": "Enforce authentication and session validation before processing sensitive user/billing data."
        }
      ]
    },
    "validation": { "score": 70, "weight": 20, "deduction": 23, "findings": [] },
    "errorHandling": { "score": 80, "weight": 10, "deduction": 9, "findings": [] },
    "testing": { "score": 30, "weight": 10, "deduction": 10, "findings": [] },
    "reliability": { "score": 85, "weight": 10, "deduction": 10, "findings": [] }
  }
}

Configuration (ship-risk.config.js)

Generate a starter configuration file:

npx ship-risk config init

Customize weights, ignore patterns, allowlists, and rule severities:

/**
 * @type {import('ship-risk').ShipRiskConfig}
 */
module.exports = {
  // Ignored paths
  ignore: [
    '**/fixtures/**',
    '**/*.mock.*',
    '**/vendor/**',
  ],

  // Category weight distribution (sum to 100)
  weights: {
    secrets: 25,
    auth: 25,
    validation: 20,
    errorHandling: 10,
    testing: 10,
    reliability: 10,
  },

  // Per-rule overrides ('off' | 'low' | 'medium' | 'high' | 'critical')
  rules: {
    'console-log-in-production': 'off',
    'missing-security-headers': 'low',
  },

  // Allowlist known false-positives or test tokens
  allowlist: {
    files: [
      'src/test-utils/**',
    ],
    rules: {
      'hardcoded-secret': ['fake-api-key-for-test'],
    },
  },

  options: {
    minScore: 70, // Exit code 1 if score falls below 70
  },
};

GitHub Actions CI Workflow

Add .github/workflows/ship-risk.yml to gate PRs if AI-generated code introduces unreviewed risk:

name: Ship Risk Readiness Gate

on:
  pull_request:
    branches: [main, master]

jobs:
  readiness-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20.x
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: AI-Code Readiness Audit
        run: npx ship-risk scan --min-score=70

Why Pure Static Analysis?

  • Instant Execution: Scans whole repositories in milliseconds using Babel AST parsing.
  • 🔒 100% Offline & Private: Zero LLM API calls, zero code sent over the network.
  • 💸 Zero Cost in CI: No token charges, rate limits, or API key dependencies.
  • 🎯 Deterministic: Run it 100 times, get the exact same reproducible score and deduction report.

Sibling Project

Check out predeploy-check — scans project deployment configurations (Render, Vercel, Railway, Python wheels, Procfiles, and package engines) before pushing to production.


License

MIT © Alok Kushwaha