METHODOLOGY · 05 · /METHODOLOGY

What we check & how it's weighted.

Every claim ties to a specific rule, a specific rubric version, and a specific finding's hashed evidence. Reproducible by any third party offline.

FORMULA · 01

Scoring formula.

Five sub-scores, each capped at 100 and penalised per finding, combine by a fixed weight into one aggregate.

Security
35%
Supply chain
20%
Maintenance
15%
Transparency
15%
Community
15%
aggregate round(0.35·Security + 0.20·Supply Chain + 0.15·Maintenance + 0.15·Transparency + 0.15·Community)

Each sub-score = max(0, 100 − Σ per-finding penalty). Because security is only 35% of the weight, a serious flaw would otherwise be averaged away — so a single active critical finding caps the whole aggregate at 15, and an active high at 45. This severity ceiling keeps a security failure in the red band no matter how clean the other axes are.

  • ≥ 80 Green safe to install
  • 60–79 Yellow caveats present
  • 40–59 Orange significant issues
  • 0–39 Red do not install
RULES · 02

The rules.

Every check we run is spelled out here — what it looks for, why it matters, how serious it is, and how to fix it, with each rule mapped to the OWASP LLM Top 10, MITRE ATLAS, and CWE where it applies. Search by name, severity, or framework, then export the list as CSV.

Severity
Showing 55 of 55 rules

Hook pipes a remote script straight into a shell

SS-HOOKS-RCE-CURL-PIPE-01 Remote code execution
CRITICAL active 35 weight

This hook runs automatically on an agent event, with no chance for you to review it first. The spotted command the flagged value pipes whatever the remote server returns at that moment straight into a shell — if the URL is ever compromised, attacker code runs on your machine.

Detection logic

regex `(?i)\b(?:curl|wget|fetch|invoke-webrequest|iwr)\b[^|;\n]*\|\s*(?:bash|sh|zsh|fish|powershell|pwsh|cmd|python|node|perl|ruby)\b` against .claude/hooks/**, hooks/**, **/*.hook.sh, **/*.hook.ps1, **/*.hook.bat, **/SessionStart*, **/SessionEnd*, **/PreToolUse*, **/PostToolUse*

Limitations (3)
  • Cannot detect the pattern when curl output is written to a file first then executed in a separate command. The two-step variant requires a sequence-aware analyzer (deferred to v2).
  • Cannot detect dynamic-URL construction (e.g. curl "$BASE/install.sh" | bash where $BASE is variable).
  • PowerShell IWR pipelines have many equivalent phrasings; the regex covers the canonical ones.

Hook recursively force-deletes a risky path

SS-HOOKS-RCE-RMRF-01 Command execution
CRITICAL active 35 weight

This hook runs automatically on an agent event, with no chance for you to stop it. The spotted command the flagged value recursively force-deletes a root, home, or variable-expanded path — if the path resolves wrong at runtime, it irreversibly destroys data.

Detection logic

regex `(?i)\brm\s+(?:-[rRfF]+\s+|--recursive\s+|--force\s+)+(?:/(?:\s|$|\*|[a-zA-Z][a-zA-Z0-9/_-]*)|\$\w+|~/?\s*$|"\$\{?\w+\}?")` against .claude/hooks/**, hooks/**, **/*.hook.sh, **/*.hook.ps1, **/SessionStart*, **/SessionEnd*, **/PreToolUse*, **/PostToolUse*

Limitations (3)
  • Cannot detect `rm -rf` with paths constructed via complex variable expansion (the rule catches `$VAR` directly but not `"${BASE}/${SUBDIR}"` chains).
  • Cannot detect PowerShell `Remove-Item -Recurse -Force` equivalents — that pattern is a v2 extension.
  • Cannot distinguish a `rm -rf` that legitimately cleans a known temp directory from one that destroys user data; the rule treats hook-scope `rm -rf` as universally suspicious.

BiDi-override characters reorder text in an MCP tool description

SS-MCP-POISON-BIDI-01 Prompt injection
CRITICAL active 35 weight

An MCP tool's description is read by the agent as trusted instructions. This one embeds bidirectional-override characters (the flagged value) so the manifest renders one thing to a human reviewer but tokenizes a different, reordered instruction to the agent.

Detection logic

regex `[\u{202A}-\u{202E}\u{2066}-\u{2069}]` against tools/manifest.json, **/tools/manifest.json, manifest.json, **/server.py, **/server.ts, **/server.js, **/*.toolmanifest.json

Limitations (2)
  • Cannot detect BiDi attacks via inherent-RTL scripts (Arabic / Hebrew text used in MCP tools for non-English users).
  • Cannot distinguish legitimate i18n use of BiDi overrides from injection.

Oversized MCP tool description (2000+ characters)

SS-MCP-POISON-DESCRIPTION-CREEP-01 Tool poisoning
CRITICAL active 35 weight

An MCP tool's description is injected into the agent's context as trusted instructions. This one runs past 2000 characters — far beyond the 100–500 a real tool needs — room to bury reasoning chains or system-prompt overrides a human reviewer skims past.

Detection logic

regex `(?is)"description"\s*:\s*"[^"]{2000,}"` against tools/manifest.json, **/tools/manifest.json, manifest.json, **/*.toolmanifest.json

Limitations (3)
  • Length-based heuristic — does not analyze the description content. A legitimate complex tool may have a long description; vendor-appeal data will tune the threshold.
  • Cannot detect description-creep injected via dynamic construction (server-side string concatenation).
  • Cannot detect multi-line JSON-formatted descriptions where the length is hidden by line wrapping in the source view.

Hidden-looking MCP tool name signals a shadow tool

SS-MCP-POISON-SHADOW-TOOL-01 Tool poisoning
CRITICAL active 35 weight

This server publishes a tool whose name (the flagged value) uses an "internal/private" naming convention. The agent still sees and may invoke it, but a human reviewing the manifest skips over names that visually signal "not for me" — letting a hidden tool act unreviewed.

Detection logic

regex `(?is)"name"\s*:\s*"[^"]*(?:_internal|__|\.hidden|_meta|_sys)[^"]*"` against tools/manifest.json, **/tools/manifest.json, manifest.json, **/*.toolmanifest.json

Limitations (2)
  • Heuristic-based: detects tool naming conventions suggestive of hidden / shadow tools. Cannot detect a shadow tool with a normal-looking name that becomes hidden via runtime registration order.
  • Cannot detect shadow tools registered exclusively at runtime (no entry in the static manifest).

Invisible Unicode tag characters hidden in an MCP tool description

SS-MCP-POISON-UNICODE-TAG-01 Prompt injection
CRITICAL active 35 weight

An MCP tool's description is fed into the agent's context as trusted instructions. This one hides invisible plane-14 tag characters (the flagged value) the agent tokenizes as commands, while a human reading the manifest sees the description unchanged.

Detection logic

regex `[\u{E0000}-\u{E007F}]` against tools/manifest.json, **/tools/manifest.json, manifest.json, **/server.py, **/server.ts, **/server.js, **/*.toolmanifest.json

Limitations (3)
  • Cannot detect tag-channel characters re-encoded as numeric entities; rule operates on decoded text only.
  • Cannot detect tag-channel chars embedded only in runtime-constructed tool descriptions (e.g. a tool whose description is f-stringed from user input).
  • Server-source detection is regex-based; obfuscation via string concatenation evades the rule.

Reads your AWS credentials file

SS-PLUGIN-SECRET-EXFIL-AWS-FILES-01 Credential exfiltration
CRITICAL active 35 weight

This plugin references the AWS credentials file or the access-key fields stored inside it (the flagged value). Those are long-lived keys with broad cloud access, so any code that reads them can hand your whole AWS account to whatever it contacts next.

Detection logic

regex `(?i)(~/.aws/credentials|~/.aws/config|/\.aws/credentials|aws_access_key_id|aws_secret_access_key|aws_session_token)` against **/*.py, **/*.ts, **/*.js, **/*.mjs, **/*.cjs, **/*.go, **/*.rb, **/*.java

Limitations (3)
  • Legitimate plugins that interact with AWS (deployment tools, S3 clients, etc.) need to reference the credentials file path. The rule's coarse detection means FP risk on every AWS-using plugin.
  • Cannot distinguish a plugin that reads .aws/credentials in a documented, user-consented flow from one that does so for exfiltration.
  • v2 will refine via composite (AWS-file read PLUS unexpected-endpoint HTTP call).

Reads environment variables and makes outbound HTTP calls in the same plugin

SS-PLUGIN-SECRET-EXFIL-ENV-NET-01 Credential exfiltration
CRITICAL active 35 weight

This plugin reads from the environment (where API keys, tokens, and AWS credentials live) and also makes outbound network calls. When both sit in the same code, a secret read from the env can be packed into a request and sent off the machine the moment the plugin runs.

Detection logic

AND of 2 sub-triggers

Limitations (3)
  • Composite trigger detects only the *coexistence* of env-read and HTTP-call primitives in the same plugin. Cannot prove that env values flow into HTTP bodies (taint analysis is deferred to v2).
  • FP risk on legitimate plugins that legitimately read env (e.g. an API key) AND call out (e.g. to the API endpoint that requires the key). The pattern is normal for any service-integration plugin; treat the rule as a signal-to-review, not a verdict.
  • Cannot detect dynamic env access via Reflect / getattr / runtime-string.

Contains a committed GitHub token

SS-PLUGIN-SECRET-EXFIL-GH-TOKEN-01 Credential exfiltration
CRITICAL active 35 weight

A GitHub token (the flagged value) is committed directly into this plugin's source. Anyone who reads the repo — including everyone who installs the plugin — gets the token, so it must be treated as already compromised.

Detection logic

regex `\b(?:ghp_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{82}|gho_[A-Za-z0-9]{36}|ghu_[A-Za-z0-9]{36}|ghs_[A-Za-z0-9]{36}|ghr_[A-Za-z0-9]{36})\b` against **/*.py, **/*.ts, **/*.js, **/*.mjs, **/*.cjs, **/*.go, **/*.rb, **/*.java, **/*.md, **/*.json, **/*.yaml, **/*.yml

Limitations (3)
  • Detects only the canonical GitHub token prefixes (ghp_ / github_pat_ / gho_ / ghu_ / ghs_ / ghr_). Cannot detect legacy 40-char hex tokens without high FP risk.
  • Detects committed tokens; cannot detect tokens read at runtime from env or from external secrets store.
  • Cannot distinguish revoked / expired tokens from active ones.

Rules file hides instructions in invisible Unicode tag characters

SS-RULES-OBFUSCATION-UNICODE-TAG-01 Obfuscation
CRITICAL active 35 weight

A rules file is injected verbatim into every agent prompt. Unicode tag-channel codepoints like the flagged value render as nothing to a human reviewer but are tokenized as text by the model — so hidden instructions steer every session while staying invisible in any editor or diff.

Detection logic

regex `[\u{E0000}-\u{E007F}]` against .cursorrules, .cursor/rules/**, .windsurfrules, .windsurf/rules/**, .continuerules, CONTINUE.md, **/rules.md, **/RULES.md

Limitations (2)
  • Cannot detect tag-channel characters re-encoded as numeric entities.
  • Cannot detect tag-channel chars in dynamically-loaded rules (e.g. rules constructed at IDE-runtime).

Bidirectional-override characters that make the text read differently than the agent sees it

SS-SKILL-INJECT-BIDI-01 Obfuscation
CRITICAL active 35 weight

A Right-to-Left Override or isolate character (U+202A–U+202E, U+2066–U+2069) reorders how the line displays without changing what the tokenizer reads — the Trojan Source trick. The file can look harmless to you while injecting hostile instructions at the token level, and the deception survives copy-paste into a sandbox.

Detection logic

regex `[\u{202A}-\u{202E}\u{2066}-\u{2069}]` against **/*.md, **/*.yaml, **/*.yml, **/*.json, **/SKILL.md, **/*.py, **/*.ts, **/*.js, **/*.sh

Limitations (2)
  • Cannot detect BiDi attacks that use RTL-marker-free scripts (Arabic / Hebrew script blocks have inherent RTL); rule scopes to explicit BiDi-override codepoints only.
  • Cannot distinguish legitimate i18n use (mixed-script documentation) from injection — fires on any explicit override character. Reviewers should examine context.

Invisible Unicode "tag" characters hidden in the instructions

SS-SKILL-INJECT-UNICODE-TAG-01 Obfuscation
CRITICAL active 35 weight

Plane-14 tag characters (U+E0000–U+E007F) render as absolutely nothing to a person reading the file in any editor, yet every LLM tokenizer turns them into real tokens. An attacker can hide a whole second instruction in them — telling the agent to drop its safety rules or exfiltrate data — that no reviewer ever sees in the source.

Detection logic

regex `[\u{E0000}-\u{E007F}]` against **/*.md, **/*.yaml, **/*.yml, **/*.json, **/SKILL.md

Limitations (3)
  • Cannot detect tag-channel characters re-encoded as numeric entities (`󠀁`); rule operates on decoded text only.
  • Cannot detect tag-channel chars hidden inside compressed payloads (gzip / brotli); only post-decompression bytes are scanned.
  • Does not distinguish documented use of plane-14 characters (rare) from injection — fires on any presence.

Hook decodes a Base64 blob and runs it as shell

SS-HOOKS-OBFUSCATION-B64-SHELL-01 Obfuscation
HIGH active 25 weight

This hook runs automatically on an agent event. The spotted command the flagged value Base64-decodes a blob and pipes it straight into a shell — encoding that hides the real commands from review, with no legitimate reason for a hook to obscure its own plain text.

Detection logic

regex `(?i)\b(?:echo|printf)\s+["']?[A-Za-z0-9+/=]{32,}["']?\s*\|\s*(?:base64\s+(?:-d|--decode)|openssl\s+base64\s+-d)\s*\|\s*(?:bash|sh|zsh)\b|\bbase64\s+(?:-d|--decode)\s+<<<\s*["'][A-Za-z0-9+/=]{32,}["']\s*\|\s*(?:bash|sh)\b` against .claude/hooks/**, hooks/**, **/*.hook.sh, **/SessionStart*, **/PreToolUse*, **/PostToolUse*

Limitations (3)
  • Cannot detect base64-shell pipelines that split the encoded payload across variables before piping.
  • Cannot detect hex-encoded or otherwise-encoded shell payloads (those would be a separate rule).
  • Cannot detect base64-decode chains that route through a temp file before execution.

Hook builds and runs commands at runtime with eval

SS-HOOKS-OBFUSCATION-EVAL-01 Obfuscation
HIGH active 25 weight

This hook runs automatically on an agent event. The spotted command the flagged value uses eval on command-substituted or variable content — the actual code is assembled at runtime from values not visible in the source, defeating any static review.

Detection logic

regex `(?i)\beval\s+["']?\$\(.*\)|\beval\s+["']?[^"'\n]*\$\{?\w+\}?[^"'\n]*["']?|\bsource\s+<\(.+\)` against .claude/hooks/**, hooks/**, **/*.hook.sh, **/SessionStart*, **/PreToolUse*, **/PostToolUse*

Limitations (3)
  • Legitimate uses of eval exist (string-substitution before execution); the FP risk is real but the hook-scope filter bounds it.
  • Cannot detect non-shell eval equivalents (Python exec(), JavaScript eval(), etc.) in hook scripts written in those languages — those would be separate rules.
  • Cannot detect indirect-eval (functions whose body executes a variable).

Hook opens a reverse shell or raw outbound socket

SS-HOOKS-RCE-NET-EGRESS-01 Remote code execution
HIGH shadow 0 weight

This hook runs automatically on an agent event. The spotted command the flagged value wires a shell to an outbound TCP socket (netcat or /dev/tcp) — a reverse shell that hands an attacker persistent, interactive access to your machine the moment it runs.

Detection logic

regex `(?i)\b(?:nc|netcat|ncat|socat)\s+(?:-[a-z]+\s+)*\S+\s+\d+|/dev/tcp/\S+/\d+|bash\s+-i\s+>&\s*/dev/tcp/` against .claude/hooks/**, hooks/**, **/*.hook.sh, **/SessionStart*, **/PreToolUse*, **/PostToolUse*

Limitations (3)
  • Cannot detect reverse-shell patterns implemented via Python sockets, Node net.connect, or other native runtime APIs (the regex covers shell-level patterns only).
  • Cannot distinguish a reverse-shell setup from a legitimate use of nc for protocol testing (rare in hook scope, but possible).
  • Operates on static text only — runtime-constructed connection strings are not detected.

Hook escalates to root without prompting you

SS-HOOKS-RCE-SUDO-UNATTENDED-01 Command execution
HIGH shadow 0 weight

This hook runs automatically on an agent event. The spotted command the flagged value invokes sudo in a way that skips the password prompt (a piped password, -n/-S, or NOPASSWD) — so it can run as root without you ever confirming.

Detection logic

regex `(?i)\bsudo\s+(?:-[ASEnk]+\s+)?\b|\becho\s+["']?\$[A-Z_]+["']?\s*\|\s*sudo\s+-S\b|\bNOPASSWD\b` against .claude/hooks/**, hooks/**, **/*.hook.sh, **/SessionStart*, **/PreToolUse*

Limitations (3)
  • Legitimate use case: installation hooks for tools that genuinely require root (rare in agent-tool ecosystems). Shadow window measures real-world FP.
  • Cannot distinguish a sudo invocation that would prompt the user (acceptable) from a sudo invocation backed by NOPASSWD or a piped-password (unacceptable).
  • Does not cover Windows runas / elevation equivalents — v2 extension.

MCP server spawns subprocesses without declaring the capability

SS-MCP-CAP-UNDECLARED-01 Undeclared capability
HIGH shadow 0 weight

The server's source spawns processes (e.g. subprocess, child_process, exec()) but its manifest never declares that capability, so the consuming client can't warn the user that this server may run shell commands on their machine.

Detection logic

AND of 2 sub-triggers

Limitations (3)
  • Heuristic detection of process-spawning primitives — cannot detect dynamically-loaded process libraries (e.g. importlib-resolved subprocess wrappers).
  • Manifest capability declarations are advisory; the MCP protocol does not enforce them. The rule flags discrepancy as a transparency signal, not a hard guarantee.
  • FP risk on MCP servers that subprocess only for legitimate internal lifecycle (worker management, not user-facing tool execution). Shadow window measures.

Zero-width characters hidden in an MCP tool manifest

SS-MCP-POISON-ZWSP-01 Obfuscation
HIGH active 25 weight

An MCP tool's description is read by the agent as trusted instructions. This manifest packs three or more invisible zero-width characters (the flagged value) that the agent tokenizes but a human reviewer cannot see — a way to smuggle hidden instructions past review.

Detection logic

regex `[\u{200B}-\u{200D}\u{2060}\u{FEFF}]` against tools/manifest.json, **/tools/manifest.json, manifest.json, **/*.toolmanifest.json

Limitations (3)
  • Requires ≥3 zero-width characters to fire (FP reduction).
  • Cannot detect zero-width characters re-encoded as numeric entities.
  • Cannot detect zero-width characters in dynamically-constructed tool descriptions.

Reads your SSH private key

SS-PLUGIN-SECRET-EXFIL-SSH-01 Credential exfiltration
HIGH active 25 weight

This plugin references an SSH private-key path or a private-key file header (the flagged value). An SSH private key authenticates you to servers and Git remotes, so code that reads it can impersonate you wherever that key is trusted.

Detection logic

regex `(?i)(~/.ssh/id_rsa|~/.ssh/id_ed25519|~/.ssh/id_ecdsa|/\.ssh/id_[a-z]+|BEGIN\s+(?:RSA|OPENSSH|DSA|EC)\s+PRIVATE\s+KEY)` against **/*.py, **/*.ts, **/*.js, **/*.mjs, **/*.cjs, **/*.go, **/*.rb, **/*.java

Limitations (3)
  • Legitimate SSH-using plugins (git wrappers, SSH-key-rotation tools) reference the canonical paths.
  • Cannot detect runtime-resolved key paths (e.g. paths read from config).
  • Cannot detect direct memory read of the SSH agent.

Sends data to a hardcoded chat or capture webhook

SS-PLUGIN-SECRET-EXFIL-WEBHOOK-01 Credential exfiltration
HIGH shadow 0 weight

This plugin embeds a chat-platform or request-capture webhook URL (the flagged value). Webhooks are the classic exfiltration drop: a plugin collects env, files, or system info and posts it to a hardcoded endpoint the attacker watches.

Detection logic

regex `(?i)https://(?:hooks\.slack\.com/services/|discord(?:app)?\.com/api/webhooks/|outlook\.office\.com/webhook/|api\.telegram\.org/bot|webhook\.site/|requestcatcher\.com/|pipedream\.com/|n8n\.cloud/|zapier\.com/hooks/)\S+` against **/*.py, **/*.ts, **/*.js, **/*.mjs, **/*.cjs, **/*.go, **/*.rb, **/*.java, **/*.md, **/*.json, **/*.yaml, **/*.yml

Limitations (3)
  • Many legitimate plugins use webhook URLs (Slack notifiers, Discord bots, monitoring integrations). Shadow window measures real-world FP cost.
  • Cannot detect webhook URLs constructed at runtime from variables.
  • Cannot distinguish a user-configured legitimate webhook from a hardcoded exfiltration endpoint without consulting the rest of the plugin source for the configuration mechanism.

Long base64-encoded blob hidden in the skill documentation

SS-SKILL-INJECT-B64-PAYLOAD-01 Prompt injection
HIGH active 25 weight

A base64 string of 128+ characters appears in a documentation file. Encoded prompt injection hides the hostile instruction in base64 — invisible to keyword filters — and relies on the agent's ability to decode it at runtime. There is no normal authoring reason to embed a multi-hundred-byte base64 blob in skill docs.

Detection logic

regex `(?<![A-Za-z0-9+/=])(?:[A-Za-z0-9+/]{4}){32,}(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?(?![A-Za-z0-9+/=])` against **/*.md, **/*.yaml, **/*.yml, **/*.json, **/SKILL.md, **/CLAUDE.md

Limitations (3)
  • Cannot distinguish injection payloads from legitimate base64 (e.g. embedded test fixtures, SHA hashes presented in base64, signed manifests). Operates on the *presence* of a sufficiently long base64-shaped string in a documentation file as a signal.
  • Does not decode the payload at scan time — the engine flags the pattern; review by maintainer or vendor surfaces the decoded content.
  • Requires ≥128 base64 chars (32 quartets) to fire. Shorter strings (typical signatures / hashes) do not trigger.

Fenced code block that tells the agent to run a command

SS-SKILL-INJECT-FENCED-RUN-01 Prompt injection
HIGH shadow 0 weight

A fenced bash/python block in SKILL.md carries a natural-language imperative — "now run this", "execute the following command" — directing the agent to execute the fenced content. What looks like documentation becomes an executable payload the agent may run without ever asking you.

Detection logic

regex `(?ms)^```(?:bash|sh|zsh|powershell|pwsh|cmd|python|node|js|ts)\s*$\s+(?:.*?\b(?:please|now|then|next|first)\s+(?:run|execute|invoke|call|trigger)\b.*?|.*?(?:run|execute|invoke|call|trigger)\s+(?:this|the\s+(?:above|below|following))\s+(?:command|code|script)\b.*?)```` against **/*.md, **/SKILL.md

Limitations (3)
  • Cannot detect imperative instructions that don't use the curated verb set (run/execute/invoke/call/trigger).
  • Cannot detect fenced-imperative when the natural-language wrapper is outside the fence (most skills place instructions BEFORE a fence, not inside it).
  • May over-fire on tutorials demonstrating the safe execution of example code; shadow window measures real-world impact.

Long hex-encoded blob hidden in the skill documentation

SS-SKILL-INJECT-HEX-PAYLOAD-01 Prompt injection
HIGH active 25 weight

A hex string of 256+ characters appears in a documentation file — well above a single SHA-256 hash (64 chars). Like its base64 sibling, hex-encoding hides a hostile instruction from keyword filters while staying trivially decodable by the agent at runtime.

Detection logic

regex `(?i)(?<![0-9a-f])([0-9a-f]{256,})(?![0-9a-f])` against **/*.md, **/*.yaml, **/*.yml, **/SKILL.md, **/CLAUDE.md

Limitations (3)
  • Cannot distinguish hex-encoded injection payloads from legitimate hex constants (SHA-256 of a known artifact, signed manifest entries). Operates on the *presence* of a sufficiently long hex-shaped string in documentation as a signal.
  • Requires ≥256 hex chars (128 bytes decoded) to fire — well above typical SHA-256 (64 hex chars) so single-hash inclusions do not trigger.
  • Does not decode the payload at scan time.

"Ignore previous instructions" command embedded in the skill

SS-SKILL-INJECT-IGNORE-01 Prompt injection
HIGH shadow 0 weight

The text the flagged value is the classic direct prompt-injection phrasing. Placed in a skill body that the agent reads as trusted instructions, it tries to make the agent abandon its prior rules and follow whatever comes next — a full system-prompt override.

Detection logic

regex `(?i)\b(ignore|disregard|forget|override)\s+(all\s+)?(previous|prior|above|earlier)\s+(instructions?|prompts?|rules?|system\s+prompts?)\b` against **/*.md, **/*.yaml, **/*.yml, **/*.json, **/SKILL.md

Limitations (3)
  • False-positives on roleplay skills, jailbreak research documentation, prompt-engineering tutorials, and any meta-discussion of LLM safety. Shadow window measures real-world FP rate.
  • Cannot detect non-English equivalents of the imperative pattern. Coverage at W2 is English-only; multilingual extension is a Phase 2 RFC.
  • Cannot detect the pattern when split across formatting or hidden in comments.

Role-override jailbreak persona in the skill text

SS-SKILL-INJECT-ROLE-01 Prompt injection
HIGH shadow 0 weight

The phrase the flagged value matches a known role-override jailbreak — DAN, "developer mode", "jailbroken", "unrestricted", or an evil/malicious persona. Embedded in a skill, it tries to push the agent into an adversarial role that drops its safety constraints, without the person running the skill realizing it.

Detection logic

regex `(?i)\b(you\s+are|act\s+as|pretend\s+(to\s+be|you\s+are)|roleplay\s+as)\s+(DAN|developer\s+mode|jailbroken|unrestricted|uncensored|an?\s+(evil|malicious|harmful|amoral)\s+\w+)\b` against **/*.md, **/*.yaml, **/*.yml, **/*.json, **/SKILL.md

Limitations (3)
  • FP rate on jailbreak-research and red-team skills is expected to be non-trivial — shadow window measures real-world impact.
  • Cannot detect novel role-override personas coined after the rule lands. The DAN/developer-mode/jailbroken seed list is curated; new personas require a v2 rule revision.
  • Cannot detect role-override embedded in tool-call arguments dynamically constructed at runtime.

Zero-width characters smuggled into the instructions

SS-SKILL-INJECT-ZWSP-01 Obfuscation
HIGH active 25 weight

Zero-width spaces and joiners (U+200B–U+200D, U+2060, U+FEFF) are invisible to a human reading the file but are emitted as distinct tokens by the agent's tokenizer. Several of them clustered together — this rule fires on three or more — can carry a hidden instruction past a reviewer who sees only ordinary text.

Detection logic

regex `[\u{200B}-\u{200D}\u{2060}\u{FEFF}]` against **/*.md, **/*.yaml, **/*.yml, **/*.json, **/SKILL.md

Limitations (3)
  • Requires ≥3 zero-width characters to fire (FP reduction). A single zero-width space — e.g. a copy-paste artifact from a Slack message — does not trigger.
  • Cannot detect zero-width characters re-encoded as numeric entities (`&#x200B;`); rule operates on decoded text only.
  • Does not currently distinguish between zero-width characters used legitimately in CJK script and the same characters used adversarially.

Hook makes files world-writable

SS-HOOKS-RCE-CHMOD-WIDE-01 Security
MEDIUM shadow 0 weight

This hook runs automatically on an agent event. The spotted command the flagged value grants world-writable permissions (777 / a+rwx) — breaking least-privilege and leaving the files open for any other process on the system to tamper with.

Detection logic

regex `(?i)\bchmod\s+(?:-R\s+)?(?:777|a\+rwx|o\+rwx|0?777)\b` against .claude/hooks/**, hooks/**, **/*.hook.sh, **/SessionStart*, **/PreToolUse*, **/PostToolUse*

Limitations (3)
  • Legitimate use: hooks that prepare a shared-temp-directory or socket for cross-user access. Shadow window measures FP rate.
  • Cannot detect chmod 666 / 644 / other wide-but-not-fully-permissive patterns that still violate least-privilege.
  • Cannot detect equivalent setfacl / takeown / icacls patterns on other platforms.

Rules file commands the agent to hide or withhold information

SS-RULES-INJECT-IMPERATIVE-01 Prompt injection
MEDIUM shadow 0 weight

A rules file is loaded verbatim into the agent as standing instructions for every session. A non-disclosure imperative like the flagged value steers the agent to conceal behaviour, hide tool calls, or withhold information on every prompt — never appearing in any single conversation you'd review.

Detection logic

regex `(?im)^\s*(?:•|-|\*|\d+\.)\s*(?:always|never|must|do\s+not|don[’']t|under\s+no\s+circumstances)\s+(?:reveal|disclose|share|leak|tell\s+(?:the\s+)?(?:user|anyone)|mention)\b` against .cursorrules, .cursor/rules/**, .windsurfrules, .windsurf/rules/**, .continuerules, CONTINUE.md, **/rules.md, **/RULES.md

Limitations (2)
  • Cursor / Windsurf rule files frequently contain legitimate confidentiality instructions ('always keep API keys out of logs'). Shadow window measures FP rate.
  • Cannot distinguish user-facing imperatives (legitimate) from model-facing imperatives (suspicious).

Rules file uses look-alike characters from another script

SS-RULES-OBFUSCATION-HOMOGLYPH-01 Obfuscation
MEDIUM shadow 0 weight

A rules file is loaded verbatim into the agent. A word like the flagged value mixes Cyrillic, Greek, or mathematical look-alike letters with Latin ones — it reads normally to you but is distinct text to the model, letting an instruction evade keyword review while still steering the session.

Detection logic

regex `[\u{0400}-\u{04FF}\u{1D400}-\u{1D7FF}\u{0370}-\u{03FF}](?:[a-zA-Z]|[\u{0400}-\u{04FF}\u{1D400}-\u{1D7FF}\u{0370}-\u{03FF}]){4,}` against .cursorrules, .cursor/rules/**, .windsurfrules, .windsurf/rules/**, .continuerules, CONTINUE.md, **/rules.md, **/RULES.md

Limitations (3)
  • FP risk on multilingual rules content (legitimate use of Greek / Cyrillic identifiers in technical documentation).
  • Cannot detect single-character homoglyph swaps; only mixed-script words ≥5 chars long.
  • v2 will integrate UTS #39 confusables data.

Instruction telling the agent not to ask for approval

SS-SKILL-INJECT-DONT-ASK-01 Prompt injection
MEDIUM shadow 0 weight

The text the flagged value tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.

Detection logic

regex `(?i)\b(do\s+not|don[’']t|never|no\s+need\s+to)\s+(ask|confirm|prompt|request\s+permission|wait\s+for\s+approval|seek\s+consent|verify\s+with\s+the\s+user)\b` against **/*.md, **/SKILL.md, **/CLAUDE.md

Limitations (3)
  • Legitimate use case: autonomous-mode skills (background tasks, scheduled jobs) explicitly opt out of approval prompts. Shadow window will quantify the FP rate on this legitimate cohort.
  • Cannot distinguish skill-level autonomy declarations from injection-style mid-skill instructions; both fire on the same regex.
  • Cannot detect equivalents in non-English text.

Long emoji run that may be smuggling a hidden instruction

SS-SKILL-INJECT-EMOJI-SMUG-01 Obfuscation
MEDIUM shadow 0 weight

Long runs of emoji — especially with variation selectors and zero-width joiners — tokenize in model-specific ways that can encode an instruction while reading as harmless decoration to a person. This rule flags ten or more consecutive emoji, a length that is rare in genuine documentation but common in this obfuscation technique.

Detection logic

regex `(?u)(?:[\U0001F300-\U0001F9FF☀-➿]\u{FE0F}?\u{200D}?){10,}` against **/*.md, **/*.yaml, **/*.yml, **/SKILL.md, **/CLAUDE.md

Limitations (3)
  • Cannot distinguish emoji-smuggled payloads from heavy-emoji documentation (welcome banners, decorative section dividers). Shadow window measures real-world impact.
  • Emoji-variation-selector (FE0F) and zero-width-joiner (200D) sequences are tokenized differently across models; rule fires on the literal codepoint sequence, not on per-model token expansion.
  • Cannot detect non-emoji obfuscation via mathematical alphanumeric symbols (U+1D400+) — that pattern is covered by SS-SKILL-INJECT-HOMOGLYPH-01.

Look-alike (homoglyph) characters mixed into otherwise-Latin words

SS-SKILL-INJECT-HOMOGLYPH-01 Obfuscation
MEDIUM shadow 0 weight

A word can look like plain English while secretly containing Cyrillic, Greek, or mathematical letters that are visually identical to ASCII — Cyrillic 'а' for Latin 'a', Greek 'ο' for 'o'. This rule flags mixed-script words of five or more characters, a technique used to slip past keyword filters while reading normally to a person.

Detection logic

regex `[\u{0400}-\u{04FF}\u{1D400}-\u{1D7FF}\u{0370}-\u{03FF}](?:[a-zA-Z]|[\u{0400}-\u{04FF}\u{1D400}-\u{1D7FF}\u{0370}-\u{03FF}]){4,}` against **/*.md, **/*.yaml, **/*.yml, **/*.json, **/SKILL.md, **/CLAUDE.md

Limitations (3)
  • FP risk on multilingual documentation (Russian / Greek / mathematical) that legitimately uses non-Latin scripts. Shadow window measures the cost.
  • Cannot detect single-character homoglyph swaps in identifiers — only mixed-script words ≥5 chars long.
  • Does not currently consult a homoglyph-confusable table (UTS #39); a v2 revision will integrate the Unicode confusables data.

"Never tell the user" non-disclosure imperative in the skill

SS-SKILL-INJECT-IMPERATIVE-01 Prompt injection
MEDIUM shadow 0 weight

A bulleted imperative like the flagged value tells the agent to never reveal, disclose, or mention something to the user. Used adversarially it can instruct the agent to hide its tool calls or lie about what it did — stripping the transparency a user relies on to trust the agent.

Detection logic

regex `(?im)^\s*(?:•|-|\*|\d+\.)\s*(?:always|never|must|do\s+not|don[’']t|under\s+no\s+circumstances)\s+(?:reveal|disclose|share|leak|tell\s+(?:the\s+)?(?:user|anyone)|mention)\b` against **/*.md, **/SKILL.md, **/CLAUDE.md

Limitations (3)
  • FP risk is substantial: legitimate skills often contain instructions about confidentiality or scope boundaries. Shadow window measures real-world impact.
  • Cannot detect imperative patterns expressed indirectly ('please keep X private', 'X should remain hidden') — only the strict imperative form.
  • Does not distinguish between user-facing imperatives (legitimate) and model-facing imperatives (suspicious).

Request for the agent to reveal its system prompt

SS-SKILL-INJECT-SYS-LEAK-01 Prompt injection
MEDIUM shadow 0 weight

The text the flagged value asks the agent to disclose its hidden system prompt or initial instructions. That is often the first step of a larger attack: knowing the system prompt lets an attacker craft inputs that defeat its constraints by mimicking its own voice.

Detection logic

regex `(?i)\b(repeat|reveal|output|print|show|tell\s+me)\s+(your|the)\s+(system\s+prompt|initial\s+instructions?|original\s+prompts?|hidden\s+instructions?|prompt\s+template)\b` against **/*.md, **/*.yaml, **/*.yml, **/*.json, **/SKILL.md

Limitations (3)
  • FP risk on skills designed to introspect or debug model behaviour (prompt-engineering tutorials, evaluation toolkits).
  • Cannot detect indirect leak attempts that don't use the canonical 'system prompt' vocabulary.
  • Does not currently chain with model-level mitigations (modern models partially refuse this class of request); SaferSkills flags the intent regardless of model response.

Hook repo is maintained by a very small group

SS-HOOKS-SUPPLY-CHAIN-OWNER-XFER-01 Supply chain
HIGH active 25 weight

This hook's repo has the matches or fewer contributors. A small maintainer pool is the classic takeover target — compromising one account, or persuading them to transfer ownership, lets an attacker push a malicious update that every consumer runs automatically.

Detection logic

contributor_count lte 5

Limitations (3)
  • v1 detects only the structural signal — small contributor pool combined with the absence of an ownership-transfer announcement. The actual cross-time owner-transfer detection (GitHub ownership change events) lands in Phase B.
  • Cannot detect repo transfers between organizations that the maintainer announces clearly — the rule fires on the structural state.
  • Hook artifacts with longer ownership history naturally pass; the rule's threshold is intentionally conservative for the hook category specifically.

MCP server content changed since the last scan (possible rug-pull)

SS-MCP-SUPPLY-CHAIN-HASH-DRIFT-01 Supply chain
HIGH active 25 weight

This server's file content hashes differ from a prior scan with no matching CHANGELOG or release note. That's the rug-pull signature: a trusted server quietly updated to introduce exfiltration, persistence, or tool-poisoning after consumers learned to trust it.

Detection logic

metadata stars exists true

Limitations (3)
  • v1 trigger is a stub — the real hash-drift comparison runs against `catalog_items.content_hash_sha256` and `scans.file_hashes` JSONB diff, which lands in Phase B engine.
  • Cannot fire on first scan of a never-seen-before MCP server (no prior hash to drift from). First-scan baseline is the trigger condition.
  • Cannot distinguish maintainer-rotation drift (legitimate ownership change) from rug-pull drift (adversarial replacement).

Name is one character off an established MCP server

SS-MCP-SUPPLY-CHAIN-TYPOSQUAT-01 Supply chain
HIGH shadow 0 weight

This server's name is within one character (Levenshtein distance 1) of an established registry entry. It may be a legitimate fork — or a typosquat hoping a user fat-fingers the install command and pulls a hostile server instead of the trusted one.

Detection logic

metadata registry_listings_count gte 1

Limitations (3)
  • v1 is structural — detects MCP servers whose name is within Levenshtein distance 1 of an established registry entry. Distance and the established-set definition land in Phase B engine. Phase A stubs the trigger.
  • Cannot detect typosquatting where the name is intentionally identical but the org is different (full repo-name collision).
  • Cross-registry typosquat detection requires the registries-index population that ships with I-03 (W4).

Hook published by a brand-new account

SS-HOOKS-SUPPLY-CHAIN-AUTHOR-AGE-01 Supply chain
MEDIUM shadow 0 weight

The account publishing this hook is less than 90 days old. New accounts that publish and disappear are a known supply-chain pattern — and a hook runs with your privileges automatically, so an unestablished author warrants extra scrutiny before you trust it.

Detection logic

metadata owner_age_days lt 90

Limitations (3)
  • GitHub user account age is a weak signal — long-established accounts can also publish malicious hooks; brand-new accounts publish many legitimate ones.
  • Does not consider per-user reputation across other repos. v2 may consult OpenSSF reputation signals.
  • Phase A registers the rule shape; the trigger executor querying GitHub user metadata wires in Phase B.

MCP release ships without any signature

SS-MCP-SUPPLY-CHAIN-UNSIGNED-01 Supply chain
MEDIUM shadow 0 weight

No signature file (Sigstore, GPG, or minisign) is present in the repo, so a consumer can't verify the install bytes match what the maintainer actually published — leaving the "someone swapped the tarball" attack class open.

Detection logic

no file at **/*.sig or **/*.minisig or **/cosign.pub or **/SIGNATURES or **/.signatures.yaml

Limitations (3)
  • Most MCP servers in 2026 do not sign releases — the rule will fire on the majority of the catalog. Shadow window quantifies whether this matters operationally.
  • Detects file-presence only; does not validate signatures or verify a trust chain.
  • GitHub-Actions-signed-only releases (Sigstore via attestations) are not detected without a Sigstore API query. v2 enhancement.

CI is configured but not enforced on the default branch

SS-SKILL-MAINTENANCE-CI-BROKEN-01 Maintenance
MEDIUM active 12 weight

The repository ships a CI workflow file but the default branch has no branch protection requiring it to pass. "Has CI" then implies "tests pass on main" when nothing actually enforces that, so a green badge can mask regressions merged into the default branch.

Detection logic

AND of 2 sub-triggers

Limitations (3)
  • Cannot distinguish a CI configuration that legitimately allows main-branch failures (e.g. nightly canary jobs that exercise unstable upstream code) from one that simply isn't enforced.
  • v1 detects the *presence* of a workflow file as the signal; v2 will query the GitHub Actions API to check recent default-branch run conclusions.
  • Cannot detect CI hosted off-platform (Buildkite-hosted, self-hosted Jenkins) when no in-repo workflow file exists.

Last commit on the default branch is over a year old

SS-SKILL-MAINTENANCE-COMMIT-RECENCY-01 Maintenance
MEDIUM active 12 weight

The default branch has had no commit in more than 365 days. That points to either abandonment or a finished project at steady state — and stale code accumulates unfixed CVEs and compatibility drift over time.

Detection logic

last_commit_age_days gt 365

Limitations (3)
  • Mature, finished libraries that legitimately need no recent updates trigger this rule. The Maintenance sub-score weight (15%) limits the impact — a stable mature library still scores well overall.
  • Cannot distinguish an abandoned project from a stable one without external signals (issue response time, release cadence). The composite signal is split across multiple Maintenance rules.
  • Repository default-branch commit age only — branch-specific staleness is not assessed.

Fewer than 3 commits in the last 90 days

SS-SKILL-MAINTENANCE-COMMIT-FREQ-01 Maintenance
LOW shadow 0 weight

The default branch saw fewer than three commits in the trailing 90 days. Read alongside the last-commit-age signal, low recent activity suggests the project may not keep pace with bug reports or dependency updates.

Detection logic

commit_freq_90d lt 3

Limitations (3)
  • FP rate on stable mature libraries is real (a finished library may have <3 commits in 90 days as a sign of stability, not abandonment). Shadow window measures the cost.
  • Bot commits (dependabot, renovate) inflate the count without indicating maintainer engagement. v2 may exclude bot-authored commits from the signal.
  • Cannot distinguish commit-volume from commit-significance (a single substantial commit vs three trivial ones).

Median issue response time is over 30 days

SS-SKILL-MAINTENANCE-ISSUE-RESPONSE-01 Maintenance
LOW shadow 0 weight

Across issues opened in the last 12 months, the median time to a first maintainer response exceeds 30 days (720 hours). That means bug reports — including security reports — are unlikely to get a timely reply.

Detection logic

issue_response_p50_hours gt 720

Limitations (3)
  • Repositories with issues disabled (Issues feature off) produce no signal; the rule does not fire on those.
  • Median is sensitive to small sample sizes (n<5 issues in window). v2 will require ≥5 issues for the signal to register.
  • Counts ANY maintainer comment as a response; cannot distinguish substantive engagement from a triage acknowledgment.

Over 80% of opened issues remain open

SS-SKILL-MAINTENANCE-OPEN-ISSUE-RATIO-01 Maintenance
LOW shadow 0 weight

Across a 12-month window, more than 80% of opened issues are still open (open / (open + closed)). That suggests issues are being filed faster than they get resolved, so a report you file may sit unresolved.

Detection logic

open_issue_ratio gt 0.8

Limitations (3)
  • Repositories with issues disabled produce no signal.
  • Stale-but-not-resolved issues (legitimate edge cases, won't-fix, deferred) inflate the ratio. v2 will require ≥30 days of inactivity on the open issue before counting.
  • Repositories with a large historical issue backlog from a different maintainer era unfairly accumulate ratio. v2 may consider a rolling 12-month window.

Rules set ships without a README

SS-RULES-TRANSPARENCY-MANIFEST-01 Transparency
MEDIUM active 12 weight

This rules repository has no README. Because rule files are injected verbatim into the agent's context, an undocumented set forces consumers to read every file to learn its intent, scope, and behaviour — making hidden or surprising instructions easy to miss.

Detection logic

no file at README.md or README or .cursor/rules/README.md or .windsurf/rules/README.md

Limitations (2)
  • A README at repo root satisfies the rule even if the rules subdirectory itself is undocumented. Subdirectory-specific documentation is a future v2 refinement.
  • Cannot validate README content quality.

No LICENSE file in the repository

SS-SKILL-TRANSPARENCY-LICENSE-01 Transparency
MEDIUM active 15 weight

No LICENSE file was found. Without one, the artifact is "all rights reserved" by default under copyright law, which leaves you with no clear right to redistribute, modify, or even install it depending on your compliance posture.

Detection logic

no file at LICENSE or LICENSE.md or LICENSE.txt or COPYING or COPYING.md or LICENCE or LICENCE.md

Limitations (2)
  • Does not validate license content — a LICENSE file containing arbitrary text satisfies the rule. License-validity is enforced via a separate SPDX-identifier check (deferred).
  • Cannot detect license declarations embedded only in package.json / pyproject.toml without a separate LICENSE file. The W2 v1 rule treats the file's presence as the canonical declaration.

No skill manifest (SKILL.md) in the repository

SS-SKILL-TRANSPARENCY-MANIFEST-01 Transparency
MEDIUM active 15 weight

This capability has no SKILL.md (or skill.yaml/.yml/.json) manifest. The manifest is what declares the skill's purpose, inputs, and behavior contract, so without it you cannot tell what the skill does or how it behaves without reading every file in the repo.

Detection logic

no file at SKILL.md or **/SKILL.md or skill.yaml or skill.yml or skill.json

Limitations (2)
  • Fires only on the absence of the manifest file by canonical name; cannot detect a manifest stored under a non-canonical filename.
  • Does not validate manifest contents — a present-but-empty SKILL.md satisfies the rule. Content-validation is a separate v2 rule under consideration.

No CHANGELOG file in the repository

SS-SKILL-TRANSPARENCY-CHANGELOG-01 Transparency
LOW active 8 weight

No CHANGELOG file was found. Without a record of what changed between releases, you cannot tell a benign patch from a behavior- or license-changing update without reading the diff yourself.

Detection logic

no file at CHANGELOG.md or CHANGELOG or CHANGELOG.txt or CHANGES.md or HISTORY.md

Limitations (2)
  • Does not validate the changelog content or format (Keep a Changelog, conventional commits, etc.). Presence is the only check.
  • GitHub-Release-managed changelogs (release notes per tag) are not detected — the rule fires even when the maintainer uses release notes instead of a file. v2 may consult the GitHub Releases API.

No README in the repository

SS-SKILL-TRANSPARENCY-DESCRIPTION-01 Transparency
LOW active 5 weight

No README file was found. The README is the canonical entry point that explains what an artifact does; without it you would have to read the source or run it speculatively to find out — both unacceptable for code that auto-installs into an agent context.

Detection logic

no file at README.md or README or README.rst or README.txt

Limitations (2)
  • Does not assess README quality, length, or accuracy. A one-line README satisfies the rule.
  • Cannot consult repository-description-only documentation (GitHub repo description with no README file). v2 may treat a non-empty GitHub repo description as partial credit.

No SECURITY.md disclosure policy in the repository

SS-SKILL-TRANSPARENCY-SECURITY-01 Transparency
LOW active 8 weight

No SECURITY.md was found (checked the repo root, .github/, and docs/). Without one there is no stated way to report a vulnerability, which versions are supported, or how quickly the maintainer commits to respond — the baseline for responsible disclosure on code that runs in privileged agent contexts.

Detection logic

no file at SECURITY.md or .github/SECURITY.md or docs/SECURITY.md

Limitations (2)
  • Does not validate SECURITY.md content (presence of disclosure email, response SLA, supported-version table).
  • GitHub-Security-Advisory-only disclosure policies are not detected — the rule fires even when the maintainer publishes via GHSA without a file.

Hook has very few forks

SS-HOOKS-COMMUNITY-FORK-HEALTH-01 Community
INFO shadow 0 weight

This hook has fewer than the matches forks. Low fork counts can hint at limited community use or little third-party validation, but they are a noisy proxy — many sound hooks are rarely forked because they need no customization. This is context only and does not affect the score.

Detection logic

metadata fork_count lt 3

Limitations (3)
  • Info severity, weight 0 — does not affect score; surfaces in trace only.
  • Fork count is a noisy proxy for community use; many legitimate hooks have low fork counts because they don't need customization.
  • Cannot distinguish recent forks (active community) from historical forks (stale).

Listed on two or more independent MCP registries

SS-MCP-COMMUNITY-CROSS-REG-01 Community
INFO active 0 weight

This server appears on at least two independent registries (such as the MCP Registry, Smithery, Glama, PulseMCP, or mcp.so), a community-adoption signal that several curators independently chose to list it. It's reference context only and does not affect the score.

Detection logic

metadata registry_listings_count gte 2

Limitations (3)
  • Info severity, weight 0: this rule does NOT affect the score. It surfaces in the trace only as community-presence context.
  • Requires the Phase B registry-index data to populate the metadata field. v1 lands the rule shape; the trigger executor is wired in Phase B.
  • Cannot detect registry-listing manipulation (an attacker who lists their MCP across multiple registries inflates the score). The signal is informational only for this reason.

Rules repository has fewer than 5 stars

SS-RULES-COMMUNITY-INSTALLS-01 Community
INFO active 0 weight

This rules repository has fewer than 5 GitHub stars. Stars are a noisy proxy for community adoption and review; a low count means fewer people have vetted these rules before they were injected into an agent's context. This is context only and does not affect the score.

Detection logic

metadata stars lt 5

Limitations (3)
  • Info severity, weight 0 — surfaces in trace only.
  • Star count is a noisy community proxy.
  • Rules-set ecosystems are small in 2026; thresholds may need recalibration as the ecosystem matures.

Single-author repository

SS-SKILL-COMMUNITY-CONTRIBUTORS-01 Community
INFO shadow 0 weight

Only one contributor is detected. Shown as community context only — solo projects are common and often legitimate, so this signal carries weight 0 and does not affect the score. It lets you weigh the bus-factor risk before deep integration.

Detection logic

contributor_count eq 1

Limitations (3)
  • Single-author projects are common and often legitimate (research code, hobby tools, focused micro-libraries). Info severity reflects this.
  • Bot accounts (dependabot, renovate) inflate the contributor count without indicating real community. v2 will exclude bot accounts.
  • Cannot distinguish a solo project from one with many shadow-contributors via squash-merge from a fork.

Fewer than 10 stars on the GitHub repository

SS-SKILL-COMMUNITY-STARS-01 Community
INFO active 0 weight

The repository has under 10 GitHub stars. This is shown as community context only — stars are an easily-manipulated, low-quality proxy for adoption, so this signal carries weight 0 and does not affect the score.

Detection logic

metadata stars lt 10

Limitations (3)
  • Star count is a noisy signal: stars can be bought, manipulated, or simply absent on new-but-legitimate projects.
  • Info severity, weight 0: this rule does NOT affect the score. It surfaces in the trace only as community-context.
  • Cannot detect star-velocity (sudden spike) which would be a more valuable signal. v2 candidate.
REPRODUCIBILITY · 03

Reproducibility.

Run the same code through SaferSkills twice and you get the same result — every time. Scores come from fixed, published rules, never from an AI model making a judgment call, so anyone can re-check a verdict for themselves and reach the identical answer. No account, no API key, nothing to take on faith.

No black-box findings. When a check flags something, the report shows exactly what was found, where, and which rule caught it — so you can see the reasoning, confirm it yourself, and fix the issue.

VENDOR APPEALS · 04

Vendor right-of-reply.

Every public verdict is appealable. Maintainers commit a verification token to .saferskills/verify.txt in their repo; once verified, they can submit a public response that appears alongside their findings. Re-scans triggered within 1 hour of any push.

The vendor right-of-reply form at /items/<slug>/respond walks through the verification flow. Findings are never silently deleted — appealed findings carry the appeal outcome and rationale in the public record.

Scan a capability.

Try the methodology on your own code — ~30 seconds, no account, full report at a permalink.