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

@yourclaw/clawguard-scanner

v0.3.0

Published

Security scanner for AI agent skills

Readme

@yourclaw/clawguard-scanner

Security scanner orchestrator for AI agent skills. This package coordinates multiple scanning tools in parallel, scores severity, and produces structured reports.


Installation

npm install @yourclaw/clawguard-scanner

For local development as part of the ClawGuard project:

cd ../clawguard && make setup

Usage

Programmatic

import { scanSkill } from "@yourclaw/clawguard-scanner";

const report = await scanSkill("/path/to/skill", {
  builtinOnly: false,       // set true to skip external tools
  skipAi: true,             // skip AI review
  format: "json",           // json | markdown | sarif
});

console.log(report.status);        // "passed" | "warning" | "blocked"
console.log(report.severityScore); // 0-100
console.log(report.findings);      // Finding[]

Via the CLI

npx @yourclaw/clawguard-cli scan /path/to/skill
npx @yourclaw/clawguard-cli scan /path/to/skill --builtin-only --skip-ai
npx @yourclaw/clawguard-cli scan /path/to/skill --format sarif

Scanner Adapters

The scanner runs multiple tools in parallel using Promise.allSettled for graceful degradation. If an external tool is not installed, that scanner is skipped without failing the overall scan.

| Adapter | Tool | What it scans | Required? | | ------- | ---- | ------------- | --------- | | Builtin Pattern Matcher | @yourclaw/clawguard-rules | Prompt injection, secrets, malware, permissions | Built-in | | Gitleaks | gitleaks | Hardcoded secrets & credentials | Optional | | Semgrep | semgrep | Custom code patterns (eval, shell injection) | Optional | | MCP-Scan | mcp-scan | MCP server configuration issues | Optional | | npm audit | npm | Known CVEs in dependencies | Optional | | AI Review | Claude API | Ambiguous cases needing judgement | Optional |

Check which tools are installed

npx @yourclaw/clawguard-cli doctor

Severity Scoring

Findings are scored on a 0–100 scale with category-based multipliers:

| Category | Multiplier | | -------- | ---------- | | Prompt injection | 2.0x | | Malware | 1.5x | | Secrets | 1.2x | | Permissions | 1.0x |

Individual severity weights:

| Severity | Points | | -------- | ------ | | critical | 25 | | high | 15 | | medium | 8 | | low | 3 |

The final score is capped at 100.

Score → Recommendation

| Score | Status | Recommendation | | ----- | ------ | -------------- | | 0 | passed | install | | 1–30 | warning | install_with_warning | | 31–70 | warning | prompt_user | | 71+ | blocked | block |


Report Formats

JSON (--format json)

Full machine-readable report with all findings, metadata, and scores.

Markdown (--format markdown)

Human-readable report suitable for GitHub issues or PR comments.

SARIF (--format sarif)

SARIF 2.1.0 format for integration with GitHub Code Scanning, VS Code, and other SARIF-compatible tools.


Suppressing Findings (.clawguard-ignore)

The scanner supports a .clawguard-ignore JSON file for suppressing known false positives. Place it in your skill directory (or any parent directory) and the scanner will automatically discover it by walking up the directory tree.

This feature was introduced to support the YourClaw OpenClaw fork upstream sync pipeline, where automated scans of upstream releases can surface false positives that need to be documented and suppressed transparently. See PR #4 for the initial set of suppressions and the analysis behind each one.

You can also pass an explicit path via the ignoreFile option:

const report = await scanSkill("/path/to/skill", {
  ignoreFile: "/path/to/.clawguard-ignore",
});

// Suppressed findings are still available for auditing
console.log(report.suppressed);        // Finding[] (what was filtered out)
console.log(report.suppressionCount);  // number

File format

{
  "suppressions": [
    {
      "id": "unique-id-for-this-suppression",
      "rule": "the-rule-name-or-finding-id",
      "file": "path/fragment/to/match",
      "scanner": "semgrep",
      "justification": "Why this is a false positive",
      "addedBy": "your-name",
      "addedAt": "2026-03-02",
      "reference": "https://github.com/your-org/your-repo/pull/123"
    }
  ]
}

Field reference

| Field | Required | Description | | ----- | -------- | ----------- | | id | Yes | Unique identifier for this suppression entry | | rule | Yes | Must match the finding's name or id field | | file | Yes | Substring match against the finding's file path | | scanner | Yes | Which scanner produced the finding (semgrep, clawguard-rules, gitleaks, etc.) | | justification | Yes | Explanation of why this finding is a false positive | | addedBy | Yes | Person or bot that added the suppression | | addedAt | Yes | Date the suppression was added (ISO 8601 date) | | reference | No | URL to the PR, issue, or discussion that discovered and analyzed the finding |

Matching logic

A finding is suppressed when both conditions are true:

  1. suppression.rule equals the finding's name or id
  2. The finding's file path contains suppression.file as a substring

Audit trail

Every suppression should include a reference URL pointing to the PR or issue where the finding was discovered, analyzed, and confirmed as a false positive. This creates a transparent audit trail so that anyone reviewing suppressions can understand the full context behind each decision.

For automated pipelines (e.g. upstream sync workflows), the reference should link to the sync PR that first flagged the finding — giving future reviewers a direct path to the scan results, code analysis, and team discussion.

When to suppress vs. when to fix

Use suppressions only for confirmed false positives — cases where the scanner flags code that is actually safe. If a finding points to a real issue, fix the code instead of suppressing it.

Good reasons to suppress:

  • A shell: true flag is used safely with hardcoded arguments (no user input)
  • A unicode escape sequence is used for data formatting, not obfuscation
  • A regex pattern triggers a secrets scanner but is not an actual secret

Bad reasons to suppress:

  • The finding is inconvenient to fix right now
  • You disagree with the rule's severity (file an issue on the rule instead)

Key Types

interface Finding {
  id: string;           // e.g. "PI-001"
  severity: "critical" | "high" | "medium" | "low";
  category: string;     // e.g. "prompt-injection"
  message: string;
  file?: string;
  line?: number;
  scanner: string;      // which adapter found it
}

interface ScanReport {
  status: "passed" | "warning" | "blocked";
  severityScore: number;
  recommendation: string;
  findings: Finding[];
  metadata: SkillMetadata;
  scannedAt: string;
}

Development

# Install dependencies
npm install

# Run tests
npm run test:run        # single run
npm test                # watch mode

# Build
npm run build

# Lint
npm run lint

Adding a new scanner adapter

  1. Create src/scanners/my-adapter.ts.
  2. Implement the adapter function returning Finding[].
  3. Use isCommandAvailable() from utils.ts for graceful skip.
  4. Register in src/orchestrator.ts inside scannerTasks.
  5. Add tests in test/.

Makefile

make install    # npm install
make build      # tsup build
make test       # vitest run
make lint       # biome check
make clean      # remove dist/ and node_modules/

Contributing

See the main CONTRIBUTING.md for guidelines. The scanner is a great place to contribute new integrations — each adapter is a self-contained file in src/scanners/.


License

Apache-2.0