Back to skill

Security audit

SEO OwlsClaw - Research * Plan * Write

Security checks for vulnerabilities and agentic risk

Overview

This SEO content skill is not malicious, but it needs Review because its deploy-ready HTML path and saved brief/plan files are not controlled tightly enough.

Before installing, treat generated HTML as draft code: review and sanitize it before publishing, especially links, meta attributes, and JSON-LD. Also require explicit confirmation for seobrief/seoplan saves, check the exact destination path, and avoid overwriting existing strategy or brief files unless intended.

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
BRAIN_ARCHITECTURE.md:317
Finding
Context-Unaware Template Substitution Enables HTML and JSON-LD Injection<![CDATA[ ## Vulnerability Details **File Location**: `BRAIN_ARCHITECTURE.md:317-326`; injection sinks are present in `TEMPLATES/product_new_template.md:7-28` and `TEMPLATES/product_new_template.md:35-88` **Vulnerability Type**: Unescaped HTML, attribute, URL, and JSON-LD template substitution **Risk Level**: High ### Vulnerable Code `BRAIN_ARCHITECTURE.md:317-326`: ```python def inject_variables(template_text: str, variables: dict) -> str: """Replace ALL {PLACEHOLDER} text with actual values.""" return template_text.format(**variables) ``` ```text Rules: - Every {PLACEHOLDER} in the template must be replaced — no placeholder may survive into output - If a variable is missing from the dictionary → flag it, ask the user for the value, do not output {PLACEHOLDER} text - Schema variables ({SCHEMA_*}) are substituted in the same pass ``` Representative sinks from `TEMPLATES/product_new_template.md:7-28`: ```html <title>{TITLE} — {DESCRIPTION}</title> <meta name="description" content="{META_DESCRIPTION}"> <link rel="canonical" href="{URL_CANONICAL}"> <!-- Schema: Product --> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Product", "name": "{TITLE}", "description": "{DESCRIPTION}", "brand": "{BRAND_NAME}", "offers": { "@type": "Offer", "priceCurrency": "EUR", "price": "{PRICE_CURRENCY_PRICE}", "availability": "https://schema.org/InStock" }, "aggregateRating": { "@type": "AggregateRating", "ratingValue": "{RATING_VALUE}", "ratingCount": "{RATING_COUNT}" } } </script> ``` Representative body and URL sinks from `TEMPLATES/product_new_template.md:35-88`: ```html <h1>{H1_TITLE_BRAND_PRODUCT_KEYWORD}</h1> <p>{HERO_SUBHEADLINE_TECHNICAL_BENEFITS} — Perfect for {TARGET_USE_CASES}</p> <span class="price-tag">{DISPLAY_PRICE_EUR} / unit</span> <section class="product-description"> <h2>{H2_DESCRIPTION_OVERVIEW_FEATURES}</h2> <p>{DESCRIPTION_CONTENT_400_CHARS_MAX}</p> <p> ...[truncated 2942 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace generic string formatting with a context-aware rendering system that enables automatic HTML escaping. 2. HTML-escape every value inserted into text nodes. 3. Attribute-encode values inserted into quoted HTML attributes. 4. Construct JSON-LD as a native object and serialize it with a standards-compliant JSON serializer. Never build JSON by interpolating strings. 5. Validate all URL values before rendering: - Permit only explicitly supported schemes, normally `https`. - Reject `javascript:`, `data:`, `file:`, and other unintended schemes. - Normalize and parse URLs before applying the allowlist. 6. Treat brand profiles, briefs, plans, search-result text, and user prompts as untrusted input. 7. Add a final structural validation step for generated HTML and JSON-LD. 8. Add adversarial regression tests containing: - Single and double quotation marks. - HTML tags and event-handler attributes. - Script-closing sequences. - Newlines and control characters. - `javascript:` and `data:` URLs. 9. Do not describe generated HTML as deploy-ready unless it has passed these security checks. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:304
Finding
Mandatory Brief and Plan Saves Bypass the Declared File-Write Confirmation Boundary<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:304-305`; conflicting capability declaration at `SKILL.md:44` and corresponding save behavior documented in `COMMANDS.md:293-295` and `COMMANDS.md:371-378` **Vulnerability Type**: File writes without the separately declared confirmation step **Risk Level**: Medium ### Vulnerable Code The capability declaration in `SKILL.md:44` states: ```text | File system writes | ⚠️ Confirmation required | Agent must ask user before saving any file — never writes autonomously | ``` The workflow in `SKILL.md:304-305` instead specifies: ```text Step 7 Output write → plain text | `writehtml` → pure HTML seoplan Structured plan saved to SEO_PLANS/ seobrief Structured brief saved to SEO_BRIEFS/ ``` The command documentation also defines saving as an automatic part of command execution: ```text Generates a structured SEO content brief before writing begins. The brief is saved to `SEO_BRIEFS/<brief-id>.md` and can be passed to `write` or `writehtml` using the `--from-brief` flag ``` ```text The plan is saved to `SEO_PLANS/<plan-id>.md` and can be referenced in any `seobrief` command using the `--plan <plan-id>.<node-id>` flag. ``` ### Technical Analysis The Skill establishes an explicit least-privilege rule: every filesystem write requires user confirmation. Its operative workflows do not implement that gate. Instead, issuing `seobrief` or `seoplan` leads to a mandatory save step. A request to generate a brief or plan expresses intent to receive the requested SEO artifact, but the Skill's own capability declaration requires an additional confirmation before persisting it. No such confirmation is present between generation and the save operation. The documentation also does not define collision handling, overwrite protection, path canonicalization, or create-exclusive semantics. This inconsistency can cause the Agent to modify p ...[truncated 1516 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make chat-only output the default for both `seobrief` and `seoplan`. 2. Immediately before every filesystem write, show the resolved destination and request explicit confirmation. 3. Do not treat the initial generation command as write authorization while the capability declaration requires a separate confirmation. 4. Validate generated identifiers against a strict filename allowlist. 5. Resolve and canonicalize the destination path, then verify that it remains under the intended `SEO_BRIEFS/` or `SEO_PLANS/` directory. 6. Use create-exclusive writes by default. 7. If a destination already exists, require separate overwrite confirmation and display the affected path. 8. For scheduled commands, either obtain save authorization when the schedule is created or return the artifact without saving. 9. Update `SKILL.md`, `COMMANDS.md`, and the plan workflow so their descriptions consistently enforce the same confirmation policy. 10. Record whether an artifact was saved and report its exact path after a successful, authorized write. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (63)

Hidden Instructions

High
Category
Prompt Injection
Content
**Zone A marker in output HTML:**
```html
<!-- ZONE:AI -->
<section>...factual content...</section>
<!-- /ZONE:AI -->
```
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
**Before Replacement** (Static Template):
```html
<!-- STATIC TEMPLATE → All Placeholders Still Present! -->
<title>{TITLE}</title>
<h1>{H1_TITLE}</h1>
<p>{HERO_SUBHEADLINE}</p>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Blogpost (Example Output) -->
<!-- Generated by SEOwlsClaw v0.1 | SEO with Owls Claw (See Owls Claw) -->

<!DOCTYPE html>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Landingpage (Example Output) -->
<!-- Generated by SEOwlsClaw v0.1 | SEO with Owls Claw (See Owls Claw) -->
<!-- Passes SEO_RULES/landingpage.md + SEO_CHECKS/page-type-specific-checks.md — Landingpage required + recommended checks -->
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<p>Orders placed during the sale window ship within 24 hours, and every item still carries our full lifetime warranty. The discount applies to the price, never to the coverage. We run this sale once a year, at the end of summer, when our warehouse team clears space for next season's colorways. That's the only reason the discount exists: it isn't a markdown on gear nobody wanted, it's a clearance on the same bestsellers reviewed in our hiking gear guides.</p>
    </section>

    <!-- HOW THE SALE WORKS H2 -->
    <section class="how-it-works">
        <h2>How the Hiking Gear Sale Works</h2>
        <p>The 25% discount applies automatically at checkout on every in-stock item across hydration, carry, and layering categories. No code required. Prices update the moment the sale starts and revert the moment it ends, so what you see at checkout is what you pay, with no surprise fees added afterward. If an item sells out mid-sale, the listing is marked unavailable rather than left live with a broken checkout, so you'll never place an order we can't fulfill.</p>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<p>This event is built for hikers who already know which gear they want and are simply waiting for the right price, not for anyone chasing a bargain on gear they'll replace in a season. If you've bookmarked the EcoSmart water bottle, added a trail pack to your cart and closed the tab, or asked a friend which rain shell holds up on multi-day trips, this is the week those decisions get 25% cheaper. New to the brand? Start with our best-reviewed pieces: the EcoSmart water bottle and our signature trail pack, both linked below.</p>
    </section>

    <!-- SOCIAL PROOF H4s -->
    <section class="social-proof">
        <h4>What Our Customers Say</h4>
        <p class="rating-summary">Rated 4.8 out of 5 from over 340 verified buyers.</p>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Socialphoto (Example Output) -->
<!-- Generated by SEOwlsClaw v0.1 | SEO with Owls Claw (See Owls Claw) -->

<!DOCTYPE html>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<meta name="description" content="{META_DESCRIPTION}">
  <link rel="canonical" href="{URL_CANONICAL}">

  <!-- ✅ SCHEMA GOES HERE — after meta, before </head> -->
  <script type="application/ld+json">
  { ... }
  </script>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
### Full Template — Site-Wide (Homepage Only)

```html
<!-- Organization Schema — inject on homepage only -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Ae1

High
Category
analysis-evasion
Content
| `SKILL.md` | Entry point — this file | Always loaded first |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| `seo-output-quality-checklist.md` | Pre-output quality gates | Step 6.5 before final output |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Blogpost -->
<!-- Generated by SEOwlsClaw v0.6 -->

<!DOCTYPE html>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Blogpost -->
<!-- Generated by SEOwlsClaw v0.6 -->

<!DOCTYPE html>
<html lang="en">
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<p>{INTRO_CONTENT_500_CHARS_MAX}</p>
    </section>

    <!-- MAIN BODY H2s with Subsections -->
    <section class="main-body">
        <h2>{H2_SECTION_1_TITLE}</h2>
        <p>{BODY_CONTENT_500_CHARS_MAX}</p>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: FAQ -->
<!-- Generated by SEOwlsClaw v0.7 -->

<!DOCTYPE html>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Landingpage -->
<!-- Generated by SEOwlsClaw v0.1 | SEO with Owls Claw (See Owls Claw) -->

<!DOCTYPE html>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Productnew -->
<!-- Generated by SEOwlsClaw v0.1 | SEO with Owls Claw (See Owls Claw) -->

<!DOCTYPE html>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Socialphoto -->
<!-- Generated by SEOwlsClaw v0.1 | SEO with Owls Claw (See Owls Claw) -->

<!DOCTYPE html>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
</body>
</html>

<!-- Editing Guide: Change any {PLACEHOLDER} text directly in this file before generation -->
<!-- Photo posts focus on visual SEO with alt text, hashtags, and platform-specific formatting! -->
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
<!-- Page Type: Socialvideo -->
<!-- Generated by SEOwlsClaw v0.1 | SEO with Owls Claw (See Owls Claw) -->

<!DOCTYPE html>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
Lines L005-L007 state that the document defines the complete processing logic and that all steps are executed in the listed order with 'no exceptions.' Later lines explicitly introduce exceptions, including `seoplan` skipping Steps 4-5 (L065-L066), Steps 3-7 not running for `seoplan` (L170-L171), and Step 2f being skipped for `seoplan`/`seobrief` (L190-L191). This is an active contradiction in the documentation about control flow.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The architecture specifies `seoplan-Step G Output + Save` and elsewhere says `seobrief` content is saved, but it does not require a clear user-facing disclosure or consent before persistence. In an agent context, silent saving of user prompts, niche research, or brand strategy can create privacy, compliance, and data retention risks, especially if users assume outputs are ephemeral.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill explicitly requires confirmation before writing files for `research`, `write`, `writehtml`, and `checks`, but `seobrief` is documented to save briefs to `SEO_BRIEFS/<brief-id>.md` automatically with no comparable consent step. This creates an inconsistent safety boundary where a user may reasonably expect no disk writes without approval, yet invoking `seobrief` causes persistent local file creation that could overwrite files, leak sensitive prompts into storage, or be abused for workspace pollution.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
`seoplan` is documented to save output to `SEO_PLANS/<plan-id>.md` automatically, again without the confirmation controls required elsewhere in the skill. Because plans are generated from user-supplied niche/topic input and may be repeatedly invoked, this enables silent persistent writes that can accumulate files, expose potentially sensitive strategy data on disk, or surprise users operating in trusted repositories or constrained environments.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The file instructs the agent to always fall back to base locale values, which are explicitly English and US-oriented (`en`, `en-US`, `US`) when no override is supplied. This creates a language/locale policy risk because users are placed into a specific locale by default without an explicit opt-in or selection mechanism documented in this file.

Static analysis

No suspicious patterns detected.