Back to skill

Security audit

Keyword Research

Security checks for vulnerabilities and agentic risk

Overview

This keyword research skill is mostly coherent, but it asks agents to run user-derived shell command examples and save business research into persistent memory despite a manifest that only declares inline delivery and state read access.

Review this skill before installing. It does not show evidence of deception or destructive behavior, but users should avoid letting an agent paste raw keyword inputs into the documented shell commands, and should only allow memory writes after confirming what business, market, Search Console, and competitor information will be stored.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:49
Finding
Shell Command Injection Through User-Controlled Keyword Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 49–53 **Vulnerability Type**: User-controlled data interpolated into shell command templates **Risk Level**: High ### Vulnerable Code ```markdown **Zero-dependency local helper** (no tool needed): `python3 "${CLAUDE_PLUGIN_ROOT}/scripts/connectors/suggest.py" "<seed>" --expand` harvests free keyword ideas from Google Autocomplete (⚠️ unofficial endpoint). Search *volume / difficulty* still needs `~~SEO tool` or own Search Console data. See [scripts/connectors/README.md](../../../scripts/connectors/README.md). **Keyless live-SERP sampling**: `python3 "${CLAUDE_PLUGIN_ROOT}/scripts/connectors/firecrawl.py" search "<candidate keyword>" --limit 10` (Firecrawl keyless free tier, ~1,000 credits/mo, no key needed) shows who actually ranks for a candidate — feed the top-10 domains and formats into the intent check and the difficulty read as **Measured** evidence instead of guessing. Volume still needs `~~SEO tool` or GSC. **Keyless topic-demand proxy**: `python3 "${CLAUDE_PLUGIN_ROOT}/scripts/connectors/pageviews.py" "<Topic_Article>" --months 12` returns a topic's real Wikipedia-attention series — Measured direction and seasonality evidence when no volume tool is connected. It is *attention, not search volume*: use it to rank topics against each other and time them, never to quote a volume number. ``` ### Technical Analysis The skill instructs the agent to place user-derived seed keywords, candidate keywords, and topic names directly inside shell command strings. Double-quoting these values does not prevent command substitution. Shell constructs such as `$(...)` and backticks are still evaluated inside double quotes. If the agent replaces one of these placeholders with untrusted input and executes the resulting command through a shell, the shell can evaluate attacker-controlled substitutions before invoking the intended Python helper. Quoting may also become ineffective if the supplied valu ...[truncated 1873 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not construct a shell command by interpolating user-controlled values. 2. Invoke each helper through a process API that accepts an argument array and does not start a shell. For example, pass the executable and arguments as separate values equivalent to: ```text ["python3", helper_path, user_seed, "--expand"] ``` 3. If the agent host exposes only a shell-command interface, add a trusted wrapper that accepts structured input and invokes the helper with a non-shell subprocess API. 4. Validate the topic or keyword against an explicit policy before execution. Reject control characters and unexpected shell metacharacters rather than relying on quoting alone. 5. Keep `${CLAUDE_PLUGIN_ROOT}` under trusted host control, resolve the helper path canonically, and verify that it remains within the expected scripts directory. 6. Document that keyword values must never be concatenated into shell strings. 7. Add regression tests containing spaces, quotes, backticks, `$()`, semicolons, newlines, and option-like values to verify that every value is passed only as inert data. 8. Consider inserting `--` before positional user input where the helper supports it, preventing values beginning with `-` from being interpreted as options. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
distribution-manifest.json:2
Finding
Persistent State Writes Exceed the Declared Package Capabilities<![CDATA[ ## Vulnerability Details **File Locations**: - `distribution-manifest.json`, lines 2–6 - `SKILL.md`, lines 35–37 - `SKILL.md`, lines 101–102 **Vulnerability Type**: Capability declaration and least-privilege mismatch **Risk Level**: Medium ### Vulnerable Code The package manifest declares only inline delivery and canonical-state read access: ```json "capabilities": [ "inline-delivery", "canonical-state-read" ], "capability_ceiling": "lite", ``` The skill contract nevertheless directs the agent to write and promote information into persistent memory: ```markdown - **Writes**: a user-facing research deliverable and reusable summary. - **Promotes**: durable keyword priorities, competitor facts, and pending strategy decisions to `memory/hot-cache.md`, `memory/open-loops.md`, and `memory/research/`. ``` It later specifies a persistent output path: ```markdown Write path: `memory/research/keyword-research/YYYY-MM-DD-<topic>.md`; promote durable keyword priorities to `memory/hot-cache.md`. See [Skill Contract](../../../references/skill-contract.md) §Save Results Template. ``` ### Technical Analysis The machine-readable manifest does not declare a state-write capability, but the natural-language instructions require the agent to create research files and update shared memory. This creates a discrepancy between the permissions a reviewer or host can infer from the manifest and the behavior requested by the skill. Persistent storage may include business goals, target markets, domain strength, competitor facts, keyword priorities, and unresolved strategy decisions. Writing those values without an explicitly declared capability or a user-confirmation boundary violates least-privilege expectations and can make task data available across later sessions. This finding does not establish that the package bypasses a correctly enforced host permission check. Rather, the risk arises when a host or agent treats natural-language skill instructions as authori ...[truncated 1475 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Align the manifest with actual behavior: - Add the appropriate persistent state-write capability if the package profile permits it; or - Remove the memory-write and promotion instructions and return all results inline. 2. Require explicit user confirmation before saving research or promoting it into shared memory. 3. Clearly identify which fields will be persisted, their destination, retention period, and deletion mechanism. 4. Minimize stored information. Avoid retaining raw connected-source data, confidential business context, or unnecessary competitor details. 5. Isolate saved research by user, workspace, and project to prevent cross-context disclosure. 6. Enforce capability checks in the host independently of natural-language instructions. A skill instruction must not be treated as authorization to exceed the manifest. 7. Use narrowly scoped write paths and prevent arbitrary path selection through the topic value. Sanitize the topic before incorporating it into a filename. 8. Provide an inline-only mode and make it the default when no explicit write capability or user approval is present. 9. Add package validation that rejects any skill whose documented read/write behavior exceeds its machine-readable capability declaration. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Vague Triggers

Medium
Confidence
93% confidence
Finding
The activation description includes broad phrases like "what to write about" alongside general keyword-research intents. That wording can overlap with everyday brainstorming or editorial-planning requests, and the file does not provide negative examples or tighter constraints to distinguish when this skill should not activate.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The manifest description at L006 explicitly excludes competitor-relative coverage gaps and directs those requests to a different skill. However, the Quick Start example asks 'What keywords is [competitor URL] ranking for that I should target?', which expands the skill into competitor-oriented analysis beyond the stated boundary.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly writes and promotes research results to persistent memory files, but it does not require clear user notice or consent before storing potentially sensitive business inputs such as goals, markets, competitor facts, or connected-data outputs. In an agent environment with reusable memory, this can cause unintended retention and later disclosure of proprietary strategy or user-provided data across tasks.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The detailed instructions explicitly suggest running competitor gap analysis even though the skill metadata says this skill must not be used for competitor-relative coverage gaps and should defer to another skill. This creates scope-confusion and can cause the agent to perform tasks outside approved boundaries, leading to misrouting, inconsistent outputs, and possible misuse of connected data or tools under the wrong workflow.

Static analysis

No suspicious patterns detected.