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

ai-security-scan

v1.3.0

Published

AI-aware security scanner for source code, CI/CD pipelines and containers. Detects prompt injection, RAG/agent/MCP risks, secrets, and OWASP LLM Top 10 issues.

Downloads

1,096

Readme

ai-security-scan

AI-aware security scanner for source code, CI/CD pipelines and containers. Detects prompt injection, RAG/agent/MCP risks, secrets, and the OWASP LLM Top 10 — with a hybrid AST + regex + LLM engine.

CI License: MIT

ai-security-scan is an open-source, modular SAST tool in the spirit of Semgrep / Snyk / Trivy, but specialized for AI and LLM application security. Run it locally, in Docker, or in any CI/CD pipeline. It returns proper exit codes so it can gate your builds.


Quick start

# Scan the current directory
npx ai-security-scan .

# Scan a subfolder, write a SARIF report, fail the build on HIGH+ findings
npx ai-security-scan ./src --report console,sarif --output report.sarif --fail-on high

# Generate an interactive HTML dashboard
npx ai-security-scan . --report html --output report.html

# Build a review artifact with deterministic remediation guidance
npx ai-security-scan review . --artifact-output .ai-security-review.json

# Build a dry-run proposal artifact for fixable findings
npx ai-security-scan propose . --artifact-output .ai-security-propose.json

Docker:

docker build -t ai-security-scan .
docker run --rm -v "$(pwd)":/workspace ai-security-scan .
docker run --rm -v "$(pwd)":/workspace ai-security-scan scan /workspace --report sarif --output /workspace/out.sarif

Default Behavior

The default CLI command is intentionally simple:

npx ai-security-scan .

By default, the package:

  • runs AST + regex scanning immediately
  • attempts a built-in lightweight local LLM pass using a managed Ollama container
  • uses a fixed lightweight code model behind the scenes
  • falls back to deterministic scanning only if Docker or the local runtime is unavailable

That means most users do not need to choose a provider, model, or auth flow just to use the package in a pipeline.

For blocking CI, prefer an explicit deterministic gate:

npx [email protected] . --deterministic-gate --fail-on high

Features

  • Hybrid detection engine
    • Layer 1 — AST (ts-morph / TypeScript compiler API): semantic checks for prompt construction, dynamic code execution and insecure output handling in TS/JS.
    • Layer 2 — Regex rule packs: fast, language-aware pattern detection.
    • Layer 3 — LLM analysis (optional): sends bounded code chunks, config files, and common dependency manifests/lockfiles to an LLM and validates structured JSON output with Zod.
  • AI-focused rule packs: Prompt Injection, RAG Security, AI Agent Security, MCP Security, Secrets, OWASP LLM Top 10, plus classic AppSec (SQLi, weak crypto, TLS, CORS…).
  • Multi-language discovery: TypeScript, JavaScript, Python, C#, Java, Go, Rust, YAML, JSON, Dockerfile, Terraform.
  • Manifest coverage: common dependency files such as package.json, package-lock.json, requirements.txt, pyproject.toml, poetry.lock, Cargo.toml, Cargo.lock, go.mod, pom.xml, and Gradle build files are discoverable for scanning.
  • Multiple report formats: console, JSON, SARIF (GitHub Code Scanning), interactive HTML.
  • Built-in local LLM mode: lightweight managed local model analysis with automatic fallback to deterministic scanning when local runtime support is unavailable.
  • Workflow artifacts: review and propose commands wrap canonical scan results with explanation, remediation, fixability, proposal, and validation metadata.
  • Bounded remediation workflow: dry-run proposals for a small safe allowlist, local branch/apply staging with --apply, and draft GitHub PR / GitLab MR metadata with --open-pr.
  • Plugin SDK: ship custom rules and scanners as npm packages.
  • CI-friendly: configurable severity threshold + exit codes.
  • Fast: bounded-concurrency work pool designed for large repositories.

CLI usage

ai-security-scan [path] [options]
ai-security-scan scan [path] [options]   # alias (handy in Docker)
ai-security-scan review [path] [options]
ai-security-scan propose [path] [options]

Arguments:
  path                     Path to scan (file or directory)   [default: "."]

Options:
  -p, --path <path>        Path to scan (overrides positional argument)
  -r, --report <formats>   console | json | sarif | html  (comma-separated)
  -o, --output <file>      Output file/dir for file-based reports
  -s, --severity <level>   Minimum severity to report (low|medium|high|critical)
      --fail-on <level>    Exit non-zero at/above this severity   [default: high]
      --fail-on-sources    Sources that can fail the scan (comma-separated)
      --deterministic-gate Fail only on non-LLM findings
      --scan-scope         Whole-scan scope before analysis (full|changed-files)
      --baseline <file>    Path to a baseline file
      --ignore-file <file> Path to a suppression file
      --exclude <globs>    Extra ignore globs (comma-separated)
      --include <globs>    Restrict to these globs (comma-separated)
      --no-inline-suppressions Disable inline aiss-disable suppressions
  -c, --concurrency <n>    Number of concurrent workers
      --config <file>      Path to a config file
      --plugins <modules>  Plugin module paths (comma-separated)
      --no-color           Disable colored output
  -v, --verbose            Verbose logging
  -q, --quiet              Suppress diagnostic logging
  -V, --version            Print version
  -h, --help               Show help

Workflow-specific flags

review supports:

  • --artifact-output <file>
  • --explain-with <deterministic|hybrid|llm>

propose supports:

  • --artifact-input <file>
  • --artifact-output <file>
  • --apply to create a local branch, apply validated edits, and stage touched files
  • --open-pr to generate or create a draft GitHub PR / GitLab MR
  • --provider <github|gitlab>

Exit codes

| Code | Meaning | | ---- | ---------------------------------------------------------- | | 0 | No findings at or above the --fail-on threshold. | | 1 | Findings at or above the threshold were detected. | | 2 | Scanner error (bad config, missing path, provider error…). |

--severity controls what appears in reports. --fail-on and --fail-on-sources control what can block the process.


Configuration file

Drop a .ai-security-scan.json at the repo root (see .ai-security-scan.example.json). CLI flags override file values.

{
  "report": ["console", "sarif"],
  "output": "reports",
  "failOn": "HIGH",
  "deterministicGate": true,
  "scanScope": "full",
  "exclude": ["**/fixtures/**"],
  "workflow": {
    "review": {
      "artifactOutput": ".ai-security-review.json",
      "explainWith": "deterministic"
    },
    "propose": {
      "artifactInput": ".ai-security-review.json",
      "artifactOutput": ".ai-security-propose.json",
      "dryRun": true,
      "openPr": false,
      "provider": "github"
    }
  }
}

The following directories are always ignored: node_modules, .git, dist, build, coverage, bin, obj, vendor (plus a few others). Add more via exclude.

Workflow config notes:

  • workflow.review.explainWith defaults to deterministic
  • workflow.propose.dryRun defaults to true
  • workflow.propose.provider defaults to github
  • --apply flips propose out of dry-run mode
  • CLI flags still override config-file values

Remote draft creation tokens:

  • GitHub: GH_TOKEN or GITHUB_TOKEN
  • GitLab: GITLAB_TOKEN or GITLAB_PRIVATE_TOKEN

Review / propose workflows

The workflow surface is intentionally layered on top of the scan engine:

  • scan detects and reports findings
  • review adds explanation, remediation guidance, and fixability metadata
  • propose adds bounded patch proposals and dry-run validation results

Safety model:

  • review is advisory only
  • propose is dry-run by default
  • only a small safe allowlist currently generates concrete patch proposals
  • --apply is required before any local branch mutation happens
  • --open-pr / --provider gitlab generate draft remote metadata in dry-run mode and only create a remote PR/MR when combined with --apply

Examples:

# Deterministic review artifact
ai-security-scan review . --artifact-output .ai-security-review.json

# Hybrid review enrichment (falls back cleanly when LLM is unavailable)
ai-security-scan review . --explain-with hybrid --artifact-output .ai-security-review.json

# Dry-run proposal artifact
ai-security-scan propose . --artifact-output .ai-security-propose.json

# Build a local proposal branch and stage validated edits
ai-security-scan propose . --artifact-output .ai-security-propose.json --apply

# Dry-run GitHub draft PR metadata
ai-security-scan propose . --artifact-output .ai-security-propose.json --open-pr

# Dry-run GitLab draft MR metadata
ai-security-scan propose . --artifact-output .ai-security-propose.json --open-pr --provider gitlab

Current fixable MVP subset:

  • llm05/remote-code-trust
  • literal TLS verification disables such as rejectUnauthorized: false, verify = False, and InsecureSkipVerify: true

All other findings remain advisory until broader fixers are added.


Baselines and suppressions

Use these features to keep known or accepted findings visible in history without letting them stay active in current CI results.

  • Baseline = accepted existing findings stored in a JSON file
  • Suppression = explicit waiver through .ai-security-scan-ignore or inline comments
  • Baseline/suppression filtering happens before fail evaluation and before report visibility filtering

Baseline file format

Pass a baseline file with:

ai-security-scan . --baseline baseline.json

Supported JSON shapes:

[
  { "id": "secret/openai-api-key", "file": "src/app.ts", "line": 12 },
  { "id": "ast/prompt-injection-concat", "file": "src/chat.ts" }
]

or:

{
  "findings": [{ "id": "secret/openai-api-key", "file": "bad.ts", "line": 1 }]
}

Rules:

  • each entry must include id and file
  • line is optional and 1-based
  • if line is omitted, the entry matches that finding id anywhere in the file
  • for multi-line findings, a matching line may fall anywhere within the finding span

Ignore file syntax

By default, the scanner looks for .ai-security-scan-ignore in the scan base directory.

Each non-empty, non-comment line must be:

<finding-id> <path>[:line]

Example:

# Suppress one specific finding line
secret/openai-api-key src/app.ts:12

# Suppress this finding id anywhere in the file
ast/prompt-injection-concat src/chat.ts

If you set --ignore-file <file>, that file must exist. The default .ai-security-scan-ignore file is optional.

Inline suppressions

Supported directives:

  • aiss-disable-next-line
  • aiss-disable-line
  • aiss-disable

Examples:

// aiss-disable-next-line secret/openai-api-key
const key = 'sk-...';

// aiss-disable-next-line: secret/openai-api-key, secret/generic-assignment
const key = process.env.OPENAI_API_KEY;

const key = secret; // aiss-disable secret/openai-api-key
const prompt = userInput; // aiss-disable-line ast/prompt-injection-concat

// aiss-disable-next-line
dangerousCall();

Behavior:

  • on a comment-only line, bare aiss-disable applies to the next line
  • on a code line, bare aiss-disable applies to the same line
  • multiple ids may be separated by spaces or commas
  • if no ids are provided, all findings on the target line are suppressed

Supported comment styles:

  • // or /*: TypeScript, JavaScript, C#, Java, Go, Rust
  • #: Python, YAML, TOML, Dockerfile, Terraform
  • <!--: XML

Precedence

The scanner applies filters in this order:

  1. ignore-file and inline suppressions
  2. baseline entries
  3. remaining findings are reported and considered for exit status

If both a suppression and a baseline match the same finding, it is counted as suppressed.

Path resolution

  • baseline and ignoreFile paths are resolved relative to the scan base directory
  • for directory scans, that base is the scanned directory
  • for single-file scans, that base is the file's parent directory
  • matcher paths are normalized to scanner-relative POSIX paths

Examples:

# Directory scan: matcher paths are relative to ./repo
ai-security-scan ./repo --baseline baseline.json

# Single-file scan: matcher path should usually be "app.ts"
ai-security-scan ./repo/src/app.ts --baseline baseline.json

Configured baseline files must exist. If --baseline points to a missing file, the scan fails.


LLM analysis (Layer 3)

The package includes a built-in lightweight local LLM flow for deeper security analysis.

# Default package behavior
ai-security-scan .

The built-in local LLM mode uses a fixed lightweight code model and the following defaults:

  • local runs: suspicious
  • CI runs: changed-files

That changed-files setting is LLM-only. If you want to scope the entire scan before AST, regex, plugins, and LLM, use:

ai-security-scan . --scan-scope changed-files

That keeps local model analysis lightweight enough for most projects.

Behind the scenes, the CLI starts a temporary ollama/ollama container when local runtime support is available, runs the LLM analysis, and then stops the container when the scan completes.

Requirements for the built-in local LLM mode:

  • the machine or CI runner must have Docker available
  • the runner must be allowed to start containers
  • the first run may spend time pulling the model image and model weights
  • if Docker is unavailable, the scan still runs with AST + regex detection only

Free local model path

Current fixed lightweight model:

qwen2.5-coder:3b

You do not need to pass a provider or model flag to use it.

If you want to disable the built-in local LLM during testing or controlled environments, set:

AI_SECURITY_SCAN_DISABLE_LLM=true

Recommended CI workflows

Deterministic blocking gate

AI_SECURITY_SCAN_DISABLE_LLM=true npx [email protected] . --fail-on high

or

npx [email protected] . --deterministic-gate --fail-on high

For PR-focused runs, you can also scope the whole scan to changed files:

npx [email protected] . --deterministic-gate --scan-scope changed-files --fail-on high

Broader advisory scan with local LLM findings still reported

npx [email protected] . --report console,sarif --output results.sarif --fail-on high --fail-on-sources ast,regex,plugin

That keeps LLM findings visible in reports while preventing them from blocking the build.

When --scan-scope changed-files cannot resolve git context safely, the scanner falls back to a full scan.


Programmatic API

import { runScan, resolveConfig, shouldFail } from 'ai-security-scan';

const config = resolveConfig({ path: './src', failOn: 'HIGH' });
const result = await runScan(config);

console.log(result.stats);
if (shouldFail(result, config)) process.exit(1);

Workflow APIs are also available:

import {
  loadWorkflowArtifact,
  runProposeWorkflow,
  runReviewWorkflow,
  saveWorkflowArtifact,
} from 'ai-security-scan';

const reviewArtifact = await runReviewWorkflow(result, {
  toolVersion: 'dev',
  explainWith: 'deterministic',
  llmConfig: config.llm,
});
await saveWorkflowArtifact('.ai-security-review.json', reviewArtifact);

const loaded = await loadWorkflowArtifact('.ai-security-review.json');
const proposeArtifact = await runProposeWorkflow(
  { artifact: loaded },
  {
    toolVersion: 'dev',
    rootPath: config.path,
    scanConfig: config,
  },
);

Plugin SDK

Build custom rules/scanners and publish them as npm packages.

import { definePlugin, type RegexRule } from 'ai-security-scan/sdk';

const rule: RegexRule = {
  kind: 'regex',
  id: 'acme/no-todo-secrets',
  title: 'TODO near secret',
  description: 'A TODO comment references a secret.',
  severity: 'MEDIUM',
  category: 'Custom',
  recommendation: 'Resolve the TODO and remove the secret.',
  pattern: /TODO.*secret/gi,
};

export default definePlugin({ name: 'acme-rules', rules: [rule] });

Use it:

ai-security-scan . --plugins ./path/to/plugin.js

See examples/plugins/custom-plugin.ts.


CI/CD integration

Ready-to-use templates live in examples/ci:

Minimal GitHub Actions step:

- name: Security Scan
  env:
    AI_SECURITY_SCAN_DISABLE_LLM: 'true'
  run: npx [email protected] . --fail-on high

Minimal GitLab step:

ai_security_scan:
  stage: test
  image: node:20-alpine
  variables:
    AI_SECURITY_SCAN_DISABLE_LLM: 'true'
  script:
    - npx [email protected] . --fail-on high

Workflow artifacts can also be generated in CI and uploaded as build artifacts for later review:

npx ai-security-scan review . --artifact-output .ai-security-review.json
npx ai-security-scan propose . --artifact-output .ai-security-propose.json

Remote draft creation permissions/tokens:

  • GitHub draft PR creation needs a token with repo contents + pull request write access
  • GitLab draft MR creation needs GITLAB_TOKEN or GITLAB_PRIVATE_TOKEN

Architecture

src/
├─ cli.ts                 # executable entrypoint
├─ cli/                   # CLI-only helpers: options, config merge, report output
├─ app/
│  ├─ scan/               # scan orchestration and pipeline composition
│  └─ workflow/           # review/propose orchestration, artifacts, validation
├─ index.ts               # public programmatic API
├─ core/                  # types, severity, config (Zod), finding utils
├─ discovery/             # recursive file discovery + language detection
├─ engine/
│  ├─ astEngine.ts        # Layer 1 — ts-morph AST analysis
│  ├─ regexEngine.ts      # Layer 2 — regex rule execution
│  ├─ concurrency.ts      # bounded work pool
│  └─ scanEngine.ts       # public engine wrapper
├─ rules/
│  ├─ ast/                # AST rule definitions
│  ├─ registry.ts         # rule registry + enable/disable
│  └─ packs/              # prompt-injection, rag, agent, secrets, mcp, owasp-llm, appsec
├─ llm/
│  ├─ provider.ts         # LLMProvider interface + Zod schema + parser
│  ├─ providers/          # openai, azure, anthropic, ollama, local
│  ├─ factory.ts          # provider construction from config
│  └─ llmEngine.ts        # Layer 3 — chunking + aggregation
├─ plugins/               # plugin manager + public SDK
├─ reporters/             # console, json, sarif, html
├─ vcs/                   # local git prep + GitHub/GitLab draft adapter layer
└─ utils/                 # logger, text/line indexing

Design principles: clean architecture, SOLID, dependency injection (providers/reporters/plugins are swappable), and a single canonical SecurityFinding model shared across every layer. ScanResult remains the canonical detection contract; workflow artifacts wrap it with explanation, remediation, fixability, proposal, validation, and draft PR/MR metadata.

Contributor-facing architecture details live in docs/architecture.md.

Security finding model

interface SecurityFinding {
  id: string;
  title: string;
  description: string;
  severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
  file: string;
  line: number;
  category: string;
  recommendation: string;
  source: 'regex' | 'ast' | 'llm' | 'plugin';
  owaspLlm?: string; // e.g. "LLM01"
  cwe?: string; // e.g. "CWE-94"
  confidence?: number;
  // …plus column/endLine/snippet/tags
}

Development

npm install
npm run dev -- examples/vulnerable-sample   # run from source via tsx
npm run build                               # bundle with tsup
npm run lint
npm run typecheck
npm test
npm run test:coverage

Bun is supported too: bun run src/cli.ts . and bun run build.

Contributing

Contributor workflow and OpenSpec guidance live in CONTRIBUTING.md.

  • current behavior specs live under openspec/specs
  • proposed cross-cutting changes live under openspec/changes
  • release automation details live in RELEASING.md
  • user-facing changes should include a Changesets entry via npm run changeset

Versioning

This project follows Semantic Versioning. Rule additions that surface new findings are treated as minor releases; breaking CLI/SDK changes bump the major. See ROADMAP.md.

License

MIT

⚠️ This tool reduces risk but does not guarantee the absence of vulnerabilities. Use it as one layer of a defense-in-depth program.