Back to skill

Security audit

Schemaorg Site Enhancer

Security checks for vulnerabilities and agentic risk

Overview

The skill is a small SEO helper with no hidden persistence or network behavior, but its HTML injection utility can create cross-site scripting if used with untrusted page content.

Review before installing if you plan to use this on pages that include user-supplied or CMS-supplied content. The package does not look deceptive, but its injection helper should escape script-breaking characters or parse and re-serialize JSON-LD safely before publishing generated HTML.

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
src/index.js:14
Finding

HTML and JavaScript Injection Through Unsafe JSON-LD Embedding

Content
View full analysis

Vulnerability Details

File Location: src/index.js:14-17 and src/index.js:23-26
Vulnerability Type: Cross-site scripting through unsafe JSON-LD embedding
Risk Level: High

Vulnerable Code

javascript
"text": item.answer
}
}))
};
return JSON.stringify(jsonLd, null, 2);
javascript
injectJSONLD: (html, jsonLD) => {
  // Simple injection of JSON-LD script into HTML head
  const scriptTag = `<script type="application/ld+json">\n${jsonLD}\n</script>`;
  return html.replace('</head>', `${scriptTag}\n</head>`);
},

Technical Analysis

generateFAQPage() serializes attacker-controlled FAQ content with JSON.stringify(), but JSON serialization alone does not safely encode data for placement in an HTML <script> element. In HTML parsing, the character sequence </script> terminates a script element even when it appears inside a JSON string.

Additionally, injectJSONLD() accepts an arbitrary jsonLD string and interpolates it directly into an HTML script block without parsing, validation, or context-appropriate escaping. Consequently, data containing a payload such as:

text
</script><script>alert(document.domain)</script>

can close the intended application/ld+json element and introduce executable HTML or JavaScript.

Attack Path

  1. An attacker gains control of an FAQ question or answer consumed by generateFAQPage(), or directly controls the jsonLD argument passed to injectJSONLD().
  2. The attacker includes </script> followed by an executable <script> element or other active HTML content.
  3. The application generates the JSON-LD string and passes it to injectJSONLD().
  4. The resulting HTML is stored, published, or returned to a user without additional output encoding or sanitization.
  5. When a browser parses the page, it terminates the JSON-LD element at the injected closing tag.
  6. The browser interprets and executes the attacker-contro ...[truncated 793 chars]
Remediation
View remediation

Remediation Suggestions

  1. Parse JSON-LD input and reject any value that is not valid JSON. Do not accept arbitrary strings as trusted script contents.
  2. Re-serialize the parsed value with JSON.stringify() and apply HTML script-context escaping. At minimum, encode < as \u003C; also encode >, &, U+2028, and U+2029 for defense in depth.
  3. Centralize safe serialization so every generator and injection function uses the same hardened implementation.
  4. Validate expected JSON-LD structure and types before embedding it.
  5. Where practical, use a trusted DOM or framework mechanism designed to create a script element rather than constructing HTML through string interpolation.
  6. Apply a restrictive Content Security Policy as defense in depth, without treating it as a replacement for correct output encoding.
  7. Add regression tests for payloads containing </script>, mixed-case closing tags, <, >, &, U+2028, U+2029, and malicious values in every attacker-controllable FAQ field.

A hardened serialization pattern can follow this approach:

javascript
function serializeJSONLD(value) {
  return JSON.stringify(value, null, 2)
    .replace(/</g, '\\u003C')
    .replace(/>/g, '\\u003E')
    .replace(/&/g, '\\u0026')
    .replace(/\u2028/g, '\\u2028')
    .replace(/\u2029/g, '\\u2029');
}

function injectJSONLD(html, jsonLDString) {
  const parsed = JSON.parse(jsonLDString);
  const safeJSONLD = serializeJSONLD(parsed);
  const scriptTag =
    `<script type="application/ld+json">\n${safeJSONLD}\n</script>`;

  return html.replace('</head>', `${scriptTag}\n</head>`);
}
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

Static analysis

No suspicious patterns detected.