Back to skills
SkillHub ClubAnalyze Data & AIFull StackData / AISecurity

moltcops

Pre-install security scanner for AI agent skills. Detects malicious patterns before you trust code. Local-first — code never leaves your machine.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,084
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
B77.6

Install command

npx @skill-hub/cli install openclaw-skills-moltcops-skill

Repository

openclaw/skills

Skill path: skills/adamthompson33/moltcops-skill

Pre-install security scanner for AI agent skills. Detects malicious patterns before you trust code. Local-first — code never leaves your machine.

Open repository

Best for

Primary workflow: Analyze Data & AI.

Technical facets: Full Stack, Data / AI, Security.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install moltcops into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding moltcops to shared team environments
  • Use moltcops for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: moltcops
version: 1.0.0
description: Pre-install security scanner for AI agent skills. Detects malicious patterns before you trust code. Local-first — code never leaves your machine.
---

# MoltCops — Skill Security Scanner

Scan any skill for security threats **before** you install it. Detects prompt injection, data exfiltration, sleeper triggers, drain patterns, and 16 more threat categories.

**Local-first.** Your code never leaves your machine. No API calls. No uploads. No accounts.

## When to Use

- **Before installing any skill** from ClawHub, GitHub, or other sources
- **Before running** skills shared by other agents
- **When evaluating** unknown code from any source
- **After ClawHavoc**: 341 malicious skills were found on ClawHub this week. Scan first.

## How to Run

```bash
python3 scripts/scan.py <path-to-skill-folder>
```

Example:
```bash
# Scan a skill before installing
python3 scripts/scan.py ~/.openclaw/skills/suspicious-skill

# Scan a freshly downloaded skill
python3 scripts/scan.py ./my-new-skill
```

**No dependencies required** — uses only Python 3 standard library.

## Reading Results

The scanner returns three verdicts:

| Verdict | Exit Code | Meaning |
|---------|-----------|---------|
| **PASS** | 0 | No critical or high-risk threats detected. Safe to install. |
| **WARN** | 1 | High-risk patterns found. Review findings before installing. |
| **BLOCK** | 2 | Critical threats detected. Do NOT install this skill. |

## What It Detects

20 detection rules across these threat categories:

| Category | Rules | Examples |
|----------|-------|---------|
| **Prompt Injection** | MC-001, MC-002, MC-003 | System prompt override, jailbreak payloads, tool-use steering |
| **Code Injection** | MC-004, MC-005, MC-006, MC-019 | Shell injection, eval/exec, base64-to-exec, child_process |
| **Data Exfiltration** | MC-007, MC-008, MC-009, MC-010, MC-020 | Webhook URLs, env var harvesting, SSH key access, credential files |
| **Hardcoded Secrets** | MC-011, MC-012 | API keys in source, private key material |
| **Financial** | MC-013 | Drain patterns, unlimited withdrawals |
| **Lateral Movement** | MC-014 | Git credential access, repo manipulation |
| **Persistence** | MC-015, MC-016 | SOUL.md writes, cron job creation |
| **Autonomy Abuse** | MC-017 | Destructive force flags (rm -rf, git push --force) |
| **Infrastructure** | MC-018 | Permission escalation (sudo, chmod 777) |

## False Positive Handling

The scanner includes context-aware filtering to reduce false positives:

- **Env var access** (MC-008): Only flags when variable names contain KEY, SECRET, PASSWORD, TOKEN, or CREDENTIAL
- **Git operations** (MC-014): Skips standard remotes (github.com, gitlab.com, bitbucket.org)
- **Force flags** (MC-017): Only flags on destructive operations, not install scripts

## Example Output

```
MoltCops Security Scanner
========================================
Scanning: ./suspicious-skill
Files: 5
Rules: 20

FINDINGS
----------------------------------------
[CRITICAL] MC-007: Exfiltration URL (main.py:14)
[CRITICAL] MC-004: Shell Injection (helper.sh:8)
[HIGH] MC-005: Dynamic Code Execution (main.py:22)

SUMMARY
========================================
Files scanned: 5
Total findings: 3
  Critical: 2
  High:     1
  Medium:   0

VERDICT: BLOCK
Critical threats detected. Do NOT install this skill.
```

## Web Scanner

For a browser-based version with the same engine, visit: **https://scan.moltcops.com**

## About MoltCops

MoltCops protects the AI agent ecosystem from malicious skills. While VirusTotal catches known malware signatures, MoltCops catches **behavioral patterns** — drain logic, sleeper triggers, prompt injection, and data exfiltration that signature-based scanning misses.

- Web: https://moltcops.com
- Moltbook: https://moltbook.com/u/MoltCops


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### scripts/scan.py

```python
#!/usr/bin/env python3
"""MoltCops Security Scanner — local-first, no network calls."""
import json, os, re, sys

def load_rules(path):
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)

def scan_file(filepath, rules):
    findings = []
    try:
        with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
            lines = f.readlines()
    except Exception:
        return findings

    for rule in rules:
        try:
            pat = re.compile(rule["pattern"], re.IGNORECASE if rule.get("case_insensitive", True) else 0)
        except re.error:
            continue

        for i, line in enumerate(lines, 1):
            if pat.search(line):
                # False positive filters
                if rule["id"] == "MC-008":
                    if not re.search(r"(KEY|SECRET|PASSWORD|TOKEN|CREDENTIAL)", line, re.IGNORECASE):
                        continue
                if rule["id"] == "MC-014":
                    if re.search(r"(github\.com|gitlab\.com|bitbucket\.org)", line, re.IGNORECASE):
                        continue
                if rule["id"] == "MC-017":
                    if not re.search(r"(rm\s|git push.*force|git reset|del\s|destroy|drop\s)", line, re.IGNORECASE):
                        continue

                findings.append({
                    "rule_id": rule["id"],
                    "rule_name": rule["name"],
                    "severity": rule["severity"],
                    "category": rule["category"],
                    "file": filepath,
                    "line": i,
                    "matched": line.strip()[:120],
                    "description": rule["description"]
                })
    return findings

def main():
    if len(sys.argv) != 2:
        print("Usage: python scan.py <path-to-skill-folder>")
        sys.exit(1)

    skill_path = sys.argv[1]
    if not os.path.isdir(skill_path):
        print(f"Error: {skill_path} is not a directory")
        sys.exit(1)

    script_dir = os.path.dirname(os.path.abspath(__file__))
    # Check same directory first (ClawHub flattens structure), then parent
    rules_path = os.path.join(script_dir, "rules.json")
    if not os.path.exists(rules_path):
        rules_path = os.path.join(os.path.dirname(script_dir), "rules.json")
    if not os.path.exists(rules_path):
        print("Error: rules.json not found")
        sys.exit(1)
    rules = load_rules(rules_path)

    print("MoltCops Security Scanner")
    print("=" * 40)
    print(f"Scanning: {skill_path}")

    # Find files
    exts = {".md", ".py", ".js", ".ts", ".sh", ".jsx", ".tsx"}
    files = []
    for root, dirs, fnames in os.walk(skill_path):
        dirs[:] = [d for d in dirs if d not in ("node_modules", ".git", "__pycache__")]
        for fn in fnames:
            if os.path.splitext(fn)[1] in exts:
                files.append(os.path.join(root, fn))

    print(f"Files: {len(files)}")
    print(f"Rules: {len(rules)}")
    print()

    all_findings = []
    for f in files:
        all_findings.extend(scan_file(f, rules))

    critical = sum(1 for f in all_findings if f["severity"] == "CRITICAL")
    high = sum(1 for f in all_findings if f["severity"] == "HIGH")
    medium = sum(1 for f in all_findings if f["severity"] == "MEDIUM")

    if all_findings:
        print("FINDINGS")
        print("-" * 40)
        for f in all_findings:
            sev = f["severity"]
            color = {"CRITICAL": "\033[0;31m", "HIGH": "\033[1;33m", "MEDIUM": "\033[0;34m"}.get(sev, "")
            nc = "\033[0m"
            rel = os.path.relpath(f["file"], skill_path)
            print(f"{color}[{sev}]{nc} {f['rule_id']}: {f['rule_name']} ({rel}:{f['line']})")
        print()

    print("SUMMARY")
    print("=" * 40)
    print(f"Files scanned: {len(files)}")
    print(f"Total findings: {len(all_findings)}")
    print(f"  Critical: {critical}")
    print(f"  High:     {high}")
    print(f"  Medium:   {medium}")
    print()

    if critical > 0:
        print("\033[0;31mVERDICT: BLOCK\033[0m")
        print("Critical threats detected. Do NOT install this skill.")
        sys.exit(2)
    elif high > 0:
        print("\033[1;33mVERDICT: WARN\033[0m")
        print("High-risk patterns found. Review before installing.")
        sys.exit(1)
    else:
        print("\033[0;32mVERDICT: PASS\033[0m")
        print("No critical or high-risk threats detected.")
        sys.exit(0)

if __name__ == "__main__":
    main()

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### _meta.json

```json
{
  "owner": "adamthompson33",
  "slug": "moltcops-skill",
  "displayName": "Moltcops Skill",
  "latest": {
    "version": "1.0.0",
    "publishedAt": 1770727692225,
    "commit": "https://github.com/openclaw/skills/commit/5a215464bccd943b5067e1c803d4d5473d2c38ed"
  },
  "history": []
}

```