Source profileQuality 88/100Review permissions

xiaolai/nlpm/skills/nlpm/security/SKILL.md

security

Detects execution surface risks, supply chain vulnerabilities, data exfiltration vectors, and prompt injection patterns in Claude Code plugins. Use when auditing plugins for security risks, reviewing MCP server configurations, scanning hooks and scripts for vulnerabilities, or checking extensions before installation.

Source repository stars
104
Declared platforms
1
Static risk flags
4
Last source update
2026-08-04
Source checked
2026-08-04

Decision brief

What it does—and where it fits

Detects execution surface risks, supply chain vulnerabilities, data exfiltration vectors, and prompt injection patterns in Claude Code plugins.

Best for

  • Use when auditing plugins for security risks, reviewing MCP server configurations, scanning hooks and scripts for vulnerabilities, or checking extensions before installation.

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeDeclaredSource recordInstall path and trigger
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/xiaolai/nlpm --skill "skills/nlpm/security"
Safe inspection promptEditorial

Inspect the Agent Skill "security" from https://github.com/xiaolai/nlpm/blob/660db42b2f2351b5f21e2022ce8785e66218a724/skills/nlpm/security/SKILL.md at commit 660db42b2f2351b5f21e2022ce8785e66218a724. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Scanning Workflow

    1. Classify files — categorize each file by execution context (see table above) 2. Identify execution surfaces — map hooks, scripts, MCP configs, commands, and install scripts 3. Scan each surface — apply pattern tables below, matching regex against file contents 4. Apply contex…

    Classify files — categorize each file by execution context (see table above)Identify execution surfaces — map hooks, scripts, MCP configs, commands, and install scriptsScan each surface — apply pattern tables below, matching regex against file contents
  2. 02

    Context-Aware File Classification

    Before assigning severity to any finding, classify the file by its execution context:

    curl https://... | bash in README.md → Low: install instruction for end userseval $var in SKILL.md → Low: pattern shown as example to avoidnew Function(...) in CLAUDE.md → Low: educational reference
  3. 03

    Documentation Files (.md)

    Patterns in .md files are instructional content, not executable code. A curl | bash in a README documents a user action the reader types manually — the plugin never runs it. Apply this rule universally:

    curl https://... | bash in README.md → Low: install instruction for end userseval $var in SKILL.md → Low: pattern shown as example to avoidnew Function(...) in CLAUDE.md → Low: educational reference
  4. 04

    Execution Surfaces

    Claude Code plugins have five execution surfaces that must be scanned:

    Claude Code plugins have five execution surfaces that must be scanned:
  5. 05

    Dangerous Shell Patterns

    Review the “Dangerous Shell Patterns” section in the pinned source before continuing.

    Review and apply the “Dangerous Shell Patterns” source section.

Permission review

Static risk signals and limitations

Runs scripts

medium · line 68

The documentation asks the agent to run terminal commands or scripts.

| Subprocess with shell=True | `subprocess\.(call\|run\|Popen).*shell\s*=\s*True` | Unsanitized input reaches shell |

Writes files

medium · line 72

The documentation asks the agent to create, modify, or delete local files.

| File write outside repo | `> ~/`, `> /etc/`, `> /tmp/.*\.sh` | System modification |

Sends data out

high · line 80

The documentation includes sending, uploading, or posting data to a remote service.

| Network calls | `curl\s+`, `wget\s+`, `fetch\(`, `requests\.(get\|post)` | Could exfiltrate repo data to external host |

Network access

medium · line 80

The documentation includes network, browsing, or remote request actions.

| Network calls | `curl\s+`, `wget\s+`, `fetch\(`, `requests\.(get\|post)` | Could exfiltrate repo data to external host |

Runs scripts

medium · line 84

The documentation asks the agent to run terminal commands or scripts.

| Shell exec functions | Functions that execute strings as shell commands | String-to-shell boundary; injection risk |

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score88/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars104SourceRepository attention, not individual Skill quality
Compatibility1 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
xiaolai/nlpm
Skill path
skills/nlpm/security/SKILL.md
Commit
660db42b2f2351b5f21e2022ce8785e66218a724
License
ISC
Collected
2026-08-04
Default branch
main
View the original SKILL.md

Security Scan Patterns for Claude Code Plugins

Context-Aware File Classification

Before assigning severity to any finding, classify the file by its execution context:

File TypeExamplesCan Execute?Rule
Shell scripts*.sh, *.bashYesApply full severity table
Code files*.py, *.js, *.mjs, *.tsYesApply full severity table
Hook definitionshooks/hooks.jsonRuns on every tool callApply full severity table
MCP configs.mcp.jsonYes (server launch)Apply full severity table
Package manifestspackage.jsonVia npm scriptsApply full severity table
Documentation*.md (SKILL.md, CLAUDE.md, README.md)NoCap at Low — see rule below

Documentation Files (*.md)

Patterns in .md files are instructional content, not executable code. A curl | bash in a README documents a user action the reader types manually — the plugin never runs it. Apply this rule universally:

Any Critical or High pattern found in a .md file → downgrade to Low (informational). Note it as "instructional content in documentation — not executable."

Examples:

  • curl https://... | bash in README.md → Low: install instruction for end users
  • eval $var in SKILL.md → Low: pattern shown as example to avoid
  • new Function(...) in CLAUDE.md → Low: educational reference

Exception: if a .md file is explicitly referenced as a script via command: in hooks.json or executed via bash file.md, treat it as executable and apply full severity.

Scanning Workflow

  1. Classify files — categorize each file by execution context (see table above)
  2. Identify execution surfaces — map hooks, scripts, MCP configs, commands, and install scripts
  3. Scan each surface — apply pattern tables below, matching regex against file contents
  4. Apply context adjustments — downgrade documentation findings to Low per the markdown rule
  5. Validate findings — verify each Critical/High finding is in an executable context before finalizing
  6. Generate report — produce the structured report (see Report Format section)

Execution Surfaces

Claude Code plugins have five execution surfaces that must be scanned:

SurfaceFilesRisk LevelWhy
Hookshooks/hooks.json, referenced scriptsCriticalRuns on EVERY tool call automatically
Scriptsscripts/*.sh, *.py, *.jsHighExecuted by commands/agents
MCP Servers.mcp.jsonHighNetwork access, data flow
Bash in commandscommands/*.md with Bash toolMediumShell execution via Claude
Install scriptspackage.json postinstall, setup scriptsMediumRuns on install

Dangerous Shell Patterns

Critical (immediate risk)

PatternRegexWhy
Pipe to shellcurl.*|.*sh, wget.*|.*bashRemote code execution
Eval with variableseval\s+["']?\$Arbitrary code execution
Reverse shellbash\s+-i\s+>&, /dev/tcp/Backdoor
Base64 decode and execbase64.*|.*sh, base64.*|.*pythonObfuscated execution
SSH key exfiltrationcat.*\.ssh/, scp.*\.ssh/Key theft
Token exfiltrationSecrets like GITHUB_TOKEN or API keys sent to curl/wgetCredential theft

High (likely dangerous)

PatternRegexWhy
Subprocess with shell=Truesubprocess\.(call|run|Popen).*shell\s*=\s*TrueUnsanitized input reaches shell
OS system callsos\.system\(No argument escaping; full shell interpretation
Dynamic require/importrequire\(\s*\$, import\(\s*\$Attacker-controlled module path
new Function with dynamic stringnew Function\( with string concatenation or template literalArbitrary code execution from string; often used to deserialize data that could be imported directly
File write outside repo> ~/, > /etc/, > /tmp/.*\.shSystem modification
Sudo usagesudo\s+Privilege escalation
PATH modificationAppending to bashrc, zshrc, or profilePersistent system modification

Medium (context-dependent)

PatternRegexWhy
Network callscurl\s+, wget\s+, fetch\(, requests\.(get|post)Could exfiltrate repo data to external host
Environment accessprocess\.env, os\.environ, shell variable expansionMay leak tokens, keys, or secrets
File reads outside repoReading from home directory or system pathsExposes credentials or configs outside project
Runtime package installnpm install, pip install, gem installUnvetted dependency pulled at runtime
Shell exec functionsFunctions that execute strings as shell commandsString-to-shell boundary; injection risk

MCP Configuration Risks

Scan .mcp.json for:

RiskCheckSeverity
Remote serversurl field pointing to non-localhostHigh
Unknown domainsDomain not in known-safe listHigh
Broad permissionspermissions with wildcard or extensive listMedium
File system accessServer with fs or filesystem capabilityMedium
Shell accessServer with shell or execution capabilityCritical
Missing authRemote server without auth fieldHigh

Known-safe MCP domains: localhost, 127.0.0.1, modelcontextprotocol.io, github.com, api.anthropic.com

Hook Safety Rules

Scan hooks/hooks.json for:

RiskCheckSeverity
Hook runs shell scriptcommand field references .sh, .py, .jsMedium (must scan the script)
Hook uses user inputScript receives prompt or input variables without sanitizationHigh
Hook on every eventTriggers on PreToolUse or PostToolUse without tool filterMedium
Hook modifies filesScript writes to disk on every tool callMedium
Hook makes network callsScript contains network request commandsHigh

Dependency Supply Chain

Scan package.json for:

RiskCheckSeverity
postinstall scriptsscripts.postinstall existsHigh
preinstall scriptsscripts.preinstall existsHigh
Git URL dependenciesDeps pointing to git URLsMedium
Unpinned versionsWildcard or "latest" version (suppress if lockfile present: package-lock.json, bun.lock, yarn.lock, pnpm-lock.yaml)Medium

Scan requirements.txt / pyproject.toml for:

RiskCheckSeverity
Git URL depsgit+https or git+ssh URLsMedium
UnpinnedNo version pinLow
Direct URLHTTP download URLsHigh

Prompt Injection Surfaces

RiskCheckSeverity
Untrusted file content in promptsAgent reads arbitrary file then uses content in BashHigh
User input passed to shellCommand takes arguments and passes to Bash without sanitizationCritical
Template expansionVariable expansion in hook scripts with user-controlled valuesHigh

Severity Definitions

SeverityMeaningAction
CriticalImmediate exploitation risk: RCE, credential theft, backdoorBlock contribution, file security issue
HighLikely dangerous: shell injection, data exfil, privilege escalationBlock contribution, report in audit
MediumContext-dependent: network calls, env access, runtime installsReport in audit, flag for review
LowMinor concern: unpinned deps, broad permissionsReport as informational

Pre-Match Context Filter (apply BEFORE flagging)

Before generating ANY Critical or High finding from the pattern tables above, verify the matched pattern is in executable position — not quoted text being displayed, documented, echoed, or used as test data. This filter applies universally to every Critical/High pattern in this skill, not just curl | bash. The audit data has shown the same class of false positives across SEC-curl-pipe-sh, SEC-new-function-eval, SEC-eval-with-variables, and SEC-base64-decode-and-exec — pattern syntactically present in the file, but in a string context where the shell or interpreter never parses it as code.

Drop the finding silently if any of these apply:

FilterWhat to skip
Inside echo/printf/cat argumentsecho "curl X | bash", printf '%s' 'wget Y | sh' — the shell never executes the matched substring
Inside heredoc bodies fed to non-shell consumersAnything between <<EOF / <<-EOF / <<'EOF' and the closing delimiter, when the heredoc is fed to cat, echo, a variable, or a usage function — only flag when fed to bash, sh, eval, or piped to a shell
Inside single- or double-quoted strings on RHS of assignmentMSG="run: curl X | bash", JS_CODE='const x = eval(input)', INSTRUCTIONS='see: wget Y | sh' — the string is data, not code
Inside object/dict literals as test/fixture data{"jsCode": "eval(item.json.code)"} — the object value is a string sent to a remote system as workflow/test/fixture data, never parsed locally
Inside shell commentsAnything after # on a line (outside quoted strings)
Inside usage() / help() / --help output functionsFunctions whose only effect is printing text to stderr/stdout
Inside markdown code fences in .md filesAlready covered by the documentation-file rule above; reaffirm here

A pattern is in executable position only when the shell or interpreter would actually parse it as a command — not when it is a string the program displays, returns, stores, or transmits. Apply this filter BEFORE confidence assignment, not after; once a Critical/High finding is emitted, the contribute path may ship it.

Per-pattern guidance

SEC-curl-pipe-sh / download-then-execute:

  • Match curl ... | (bash|sh) only when the curl invocation is at the start of a pipeline whose right-hand side is a shell, NOT when the pattern text appears as a quoted argument to another command.
  • A chmod +x file && ./file immediately after a curl -o file ... IS executable; flag it. A chmod +x shown inside a usage heredoc is NOT; drop it.

SEC-new-function-eval / SEC-eval-with-variables:

  • Match eval(...), new Function(...), exec(...) only when the call is in executable position. Verify by reading the surrounding 5 lines: if the match is the value of an object property, the body of a string literal, or fixture/test data being passed to a remote system, drop it.
  • A python3 -c "..." block where the -c argument interpolates variables IS executable when the script runs locally; flag it.
  • A string constant jsCode: 'const result = eval(item.json.code);' defined in test data destined for an external workflow runtime is NOT executable in the audited repo; drop it.

SEC-base64-decode-and-exec:

  • Match base64 -d | sh, base64.decode(...) | exec only when the decoded output is fed to a local shell or interpreter. If the base64 is a transport encoding for code sent to a remote sandbox/container (e.g., printf X | base64 -d where X is constructed locally and shipped via stdin to an E2B sandbox), the local audit has no exposure — drop it.

If a pattern is in executable position but is intentional and trusted (e.g., a CI release script that pipes a known maintainer-controlled URL to bash, or python3 -c interpolating values from mktemp/stat/internal tools that cannot contain injection characters), mark it false_positive: true with an fp_reason explaining the trust path. The reproduction gate at the contribute step will drop it; the rule still gets the self-learning signal.

Public-by-Design Identifiers (drop SEC-hardcoded-api-key matches)

Many "API keys" embedded in client-side code are PUBLIC BY DESIGN — they identify a project to a third-party SDK but carry no privileged access. Flagging them as hardcoded secrets is a category error: the maintainer cannot remove the value without breaking the integration, and the value is already visible to any browser that visits the site.

Drop SEC-hardcoded-api-key findings silently when ALL of these apply:

FilterWhat to drop
File is under public/, static/, assets/, dist/, build/, _site/, or other published-output directoriesAnything served directly to browsers is, by construction, public. The maintainer can't make it private without redesigning the integration.
Key matches a known-public-by-design patternSee list below.
Filename indicates client-side initialization (posthog.js, gtag.js, analytics.js, mixpanel.js, sentry.js, clarity.js, etc.)Analytics SDKs require client-side identifiers to function.

Known-public-by-design key patterns:

ProviderPatternExample
PostHogstarts with phc_ (project key)phc_xxxxx...
PostHogpassed to posthog.init(KEY, ...) from a <script> tagany value
Google AnalyticsG-XXXXXXX (GA4 Measurement ID)G-1A2B3C4D5E
Google AnalyticsUA-XXXXXX-X (Universal Analytics)UA-12345-1
Google Tag ManagerGTM-XXXXXXXGTM-ABCDE12
Mixpanelpassed to mixpanel.init(TOKEN) from a <script> tagany 32-hex
SentryDSN with https:// prefix in browser-side codehttps://[email protected]/456
Reoreo.js clientID, passed to Reo.initany value
Claritypassed to clarity.init or (c,l,a,r,i,t,y) snippetany value
Amplitudepassed to amplitude.init(API_KEY, ...) from <script>any value
Hotjarnumeric hjid in _hjSettingsnumeric
Segmentanalytics.load(WRITE_KEY) from a <script> tagany value
LogRocketLogRocket.init(APP_ID) from a <script> tagany value
Stripepublishable key starts with pk_live_ or pk_test_pk_live_xxxxx
AlgoliasearchOnly key in client config (not admin key)any value

Public DSN/CSP-safe identifiers in meta tags, <script src> URLs, or ESM imports are also public by design.

What still IS a finding (never drop):

  • Stripe secret keys (sk_live_, sk_test_)
  • AWS access keys (AKIA..., ASIA...)
  • GitHub PATs (ghp_, gho_, ghu_, ghs_, ghr_)
  • OpenAI keys (sk-..., sk-proj-...)
  • Anthropic keys (sk-ant-...)
  • Database connection URLs with embedded credentials
  • Private keys (-----BEGIN ...PRIVATE KEY-----)
  • Twilio Auth Tokens, SendGrid API keys, etc. — server-side credentials
  • Any key matched in a server-side path (api/, server/, backend/, routes/, lib/server/, files NOT under public output dirs)

The discipline: ask "if this key were swapped tomorrow, would the end-user-visible product break?" If yes (analytics, tag managers, SDK identifiers), it's public-by-design — drop. If no (auth, write operations, admin endpoints), it's a real secret — flag.

Finding source: 2026-05-05 audit of wasp-lang/open-saas flagged 3 PostHog/Reo public keys in opensaas-sh/blog/public/scripts/. All 3 were self-marked false_positive: true by the scorer. Adding this filter prevents the audit cycle from being burned on the same false positive shape.

Finding Validation

After the pre-match filter, verify each surviving Critical or High result:

  • Confirm the file is in an executable context (not documentation)
  • Verify the pattern is reachable at runtime (not dead code behind a feature flag)
  • Cross-reference with the project's test suite — a pattern in test fixtures is lower risk

Report Format

The security scan section in an audit report follows this structure:

## Security Scan

| Severity | Count |
|----------|-------|
| Critical | N |
| High | N |
| Medium | N |
| Low | N |

### Findings

| # | Severity | File | Line | Pattern | Description |
|---|----------|------|------|---------|-------------|

Risk Gate

If any Critical or High findings exist, the contribute-approved label must NOT be applied. The audit report must include a prominent warning and the tracking issue must link to the security findings.

Scope Note

This skill covers the security-pattern catalog and risk-gate logic used by the security-scanner agent. For the schemas of executable artifacts the scanner inspects (hooks, scripts, MCP configs), see nlpm:conventions. For the broader anti-pattern catalog covering NL-quality findings that are not security risks, see nlpm:patterns.

Alternatives

Compare before choosing

Computed 956

mgiovani/cc-arsenal

create-skill

Create a new agent skill (or Claude Code slash command) from a plain-language description, using live spec fetching, pattern research, and an approval-gated blueprint before any files are written. Use whenever the user wants to build, scaffold, or author a new skill, subagent capability, or slash command, including phrasings like 'make a command for X', 'create a slash command', 'turn this into a reusable skill', or 'package this workflow as a skill'. Not for editing CLAUDE.md/AGENTS.md memory r

Computed 9023,781

alirezarezvani/claude-skills

research-summarizer

Structured research summarization agent skill for non-dev users. Handles academic papers, web articles, reports, and documentation. Extracts key findings, generates comparative analyses, and produces properly formatted citations. Use when: user wants to summarize a research paper, compare multiple sources, extract citations from documents, or create structured research briefs. Plugin for Claude Code, Codex, Gemini CLI, and OpenClaw.

Computed 8823,781

alirezarezvani/claude-skills

research-ops-skills

Use when planning, funding, scoping, or synthesizing enterprise research across workstreams — clinical study design, R&D program finance, market sizing/surveys, or product/user research. Triggers on "design this clinical study", "what sample size", "R&D budget", "burn rate", "capitalize or expense", "TAM SAM SOM", "market sizing", "survey design", "segment the market", "plan user interviews", "usability test", "synthesize research insights". Forks context to route to one of four Research-Operati

Computed 8723,781

alirezarezvani/claude-skills

llm-wiki

Use when building or maintaining a persistent personal knowledge base (second brain) in Obsidian where an LLM incrementally ingests sources, updates entity/concept pages, maintains cross-references, and keeps a synthesis current. Triggers include "second brain", "Obsidian wiki", "personal knowledge management", "ingest this paper/article/book", "build a research wiki", "compound knowledge", "Memex", or whenever the user wants knowledge to accumulate across sessions instead of being re-derived by