Back to skill

Security audit

Schema Markup

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent schema-markup helper, but one implementation example could teach agents to add unsafe JSON-LD code that may create cross-site scripting risk.

Review generated code before applying it to production pages. For React or Next.js JSON-LD, require a serializer that escapes characters such as '<' before placing dynamic CMS, catalog, seller, or user-controlled values inside a script tag.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
references/schema-examples.md:385
Finding
Unsafe JSON-LD Serialization Can Enable Stored Cross-Site Scripting<![CDATA[ ## Vulnerability Details **File Location**: `references/schema-examples.md:385-393` **Vulnerability Type**: Unsafe serialization of dynamic data into an inline script **Risk Level**: High ### Vulnerable Code ```jsx export default function ProductPage({ product }) { const schema = { "@context": "https://schema.org", "@type": "Product", name: product.name, // ... other properties }; return ( <> <Head> <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }} /> </Head> {/* Page content */} </> ); } ``` ### Technical Analysis The example inserts dynamically populated product data into an inline JSON-LD `<script>` element using `dangerouslySetInnerHTML`. Although `JSON.stringify()` produces valid JSON, it is not a safe HTML-script-context encoder. In particular, it does not escape the `<` character or prevent an attacker-controlled value from containing a literal `</script>` sequence. HTML parsing rules recognize `</script>` even when it appears inside a JSON string. Consequently, a malicious product name or another dynamic schema property could terminate the JSON-LD element and introduce attacker-controlled HTML or JavaScript. For example, an attacker-controlled field containing a payload conceptually equivalent to: ```text </script><script>ATTACKER_CODE</script> ``` could break out of the non-executable `application/ld+json` block. The newly introduced regular script element would then execute in the origin of the affected website. This is especially relevant when product information comes from a CMS, marketplace seller, catalog import, API integration, or another source that is not fully trusted. ### Attack Path 1. An attacker obtains the ability to create or modify a product field consumed by the schema generator, such as `product.name`. 2. The attacker places a script-closing sequence and malicious markup in that fi ...[truncated 1324 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use a serializer designed for embedding JSON in HTML script contexts. At minimum, escape HTML-significant characters after JSON serialization, particularly `<`, so that a literal `</script>` sequence cannot occur: ```jsx function serializeJsonLd(value) { return JSON.stringify(value) .replace(/</g, "\\u003c") .replace(/>/g, "\\u003e") .replace(/&/g, "\\u0026") .replace(/\u2028/g, "\\u2028") .replace(/\u2029/g, "\\u2029"); } <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: serializeJsonLd(schema) }} /> ``` Additional hardening measures should include: 1. Use a well-reviewed JSON-for-HTML serialization library where available. 2. Validate dynamic schema fields against their expected types, formats, and maximum lengths. 3. Treat CMS, marketplace, imported catalog, and API-provided values as untrusted. 4. Sanitize or reject unexpected markup in fields that should contain plain text. 5. Apply a restrictive Content Security Policy as defense in depth, while not relying on CSP as the primary fix. 6. Add regression tests containing payloads such as `</script><script>...</script>` and verify that no additional DOM elements or executable scripts are created. 7. Update the documentation example so users do not copy an unsafe implementation into production applications. ]]>
Vulnerability Patterns
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (3)

Unvalidated Output Injection

High
Category
Output Handling
Content
<Head>
        <script
          type="application/ld+json"
          dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
        />
      </Head>
      {/* Page content */}
Confidence
65% confidence
Finding
Model output is used without validation or sanitization. Unvalidated output injected into downstream contexts (SQL, shell, HTML) enables injection attacks and arbitrary code execution.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The skill description uses a very broad set of activation phrases covering many common SEO and search-related terms, which can cause the agent to invoke this skill in situations where a more appropriate or safer skill should be used. Over-broad routing increases the chance of misclassification, context leakage from unrelated tasks, and unintended execution paths, even though the content itself is not overtly malicious.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The eval explicitly rewards the skill for triggering on casual phrasing ('add schema to our blog posts') without defining boundaries that distinguish schema-markup requests from broader SEO, content, or development requests. This can cause over-broad skill activation, leading the agent to apply the wrong capability, produce irrelevant or unsafe changes, and bypass more appropriate specialist skills.

Static analysis

No suspicious patterns detected.