Back to skill

Security audit

content-claim-navigator

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated copyright-claim support purpose, but its optional shareable HTML summary needs review because untrusted claim data could be embedded unsafely if rendered naively.

Use the skill for procedural claim organization, not legal advice. Avoid pasting passwords, unnecessary personal data, or attorney communications. Do not use the shareable HTML summary unless the host renderer escapes text, validates URLs, restricts CSS/classes, and builds links/timeline rows from typed data. Run the eval scripts only with deliberate consent because they send prompts/transcripts to Anthropic.

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

Warning
Location
scripts/artist_summary_template.html:86
Finding
Unsafe Interpolation in Shareable HTML Summary Template<![CDATA[ ## Vulnerability Details **File Location**: `scripts/artist_summary_template.html:86-148` **Vulnerability Type**: Stored HTML injection / cross-site scripting through unescaped template values **Risk Level**: Medium ### Vulnerable Code ```html <header class="letterhead"> <!-- Branding slots are operator-supplied. The session must first record the operator's confirmation that they are authorized to use this letterhead, logo, font, and any artwork included. --> <img class="logo" src="{{label_logo}}" alt="{{label_name}} logo"> <div> <div class="label-name">{{label_name}}</div> <div class="subtitle">{{label_contact_line}}</div> </div> </header> <h1>What's happening with your release, in plain terms</h1> <p class="subtitle">Prepared {{prepared_date}} for {{artist_name}}</p> <div class="release"> <img class="art" src="{{album_art}}" alt="Artwork for {{release_title}}"> <div> <strong>{{release_title}}</strong><br> {{platform}} · {{event_type_plain}}<br> <span class="badge {{severity_class}}">{{severity_label}}</span> </div> </div> <section> <h2>What this is</h2> <p>{{plain_explanation}}</p> <h2>What this is not</h2> <p>{{what_it_is_not}}</p> </section> <section> <h2>Dates worth knowing</h2> <table class="timeline"> <!-- One row per timeline entry. Unconfirmed dates always carry the UNCONFIRMED badge and their confirm_by note. --> {{timeline_rows}} </table> </section> <section class="amounts"> <h2>Money, as currently understood</h2> <p>{{amounts_plain}}</p> <p class="estimate-note">These figures are estimates as of {{prepared_date}} and can change as the dispute resolves. Final numbers come from the platform's own reports, not this page.</p> </section> <section> <h2>What {{label_name}} is doing</h2> <p>{{label_actions_plain}}</p> </section> <div class="disclaimer"> This summary is a plain-language explanation prepared to keep you informed. It is not lega ...[truncated 4081 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Render the document with a maintained template engine whose HTML autoescaping is enabled by default. 2. Treat all imported claim records, operator-supplied values, notice text, and model-generated strings as untrusted. 3. Apply encoding appropriate to each output context: - HTML-escape text-node values. - Attribute-escape attribute values. - Do not interpolate arbitrary values into CSS. - Validate URLs before placing them in `src` or `href`. 4. Replace `timeline_rows` and `official_links` raw-markup inputs with typed data structures. Generate the required elements through trusted renderer code instead of accepting preassembled HTML. 5. Allowlist URL schemes and expected destinations. Permit only required schemes such as `https:` and explicitly approved embedded/local image formats. Reject `javascript:`, dangerous `data:` content, control characters, and ambiguous URL forms. 6. Restrict `severity_class` to a fixed enumeration rather than accepting arbitrary class text. 7. Restrict font selection to a predefined allowlist, or safely serialize and validate each permitted font-family token. 8. If limited rich text is required, sanitize it with a well-maintained allowlist sanitizer after rendering and before distribution. 9. When summaries are hosted, apply a restrictive Content Security Policy. At minimum, prohibit inline scripts, plugins, and unapproved network destinations. 10. Add automated security tests using: - Closing-tag and script-element payloads. - Quote-breaking attribute payloads. - Event-handler attributes. - `javascript:` and unsafe `data:` URLs. - CSS context-breakout payloads. - Malicious markup supplied through `timeline_rows` and `official_links`. 11. Document the renderer's trust boundaries and escaping guarantees so alternate host implementations cannot silently perform unsafe string replacement. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tainted flow: 'req' from os.environ.get (line 137, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
API_URL, data=body, method="POST",
        headers={"Content-Type": "application/json", "x-api-key": key,
                 "anthropic-version": "2023-06-01"})
    with urllib.request.urlopen(req, timeout=120) as resp:
        data = json.loads(resp.read())
    return "".join(b.get("text", "") for b in data.get("content", [])
                   if b.get("type") == "text")
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding indicates additional hidden behaviors such as live outbound model API calls, automated eval generation, transcript grading, red-team testing, and report writing that are unrelated to the declared creator-support purpose. If present at runtime, these behaviors could exfiltrate sensitive user content, create undisclosed copies of legal notices, and repurpose user interactions for internal testing without consent.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This finding indicates additional hidden behaviors such as live outbound model API calls, automated eval generation, transcript grading, red-team testing, and report writing that are unrelated to the declared creator-support purpose. If present at runtime, these behaviors could exfiltrate sensitive user content, create undisclosed copies of legal notices, and repurpose user interactions for internal testing without consent.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill references operational capabilities and maintenance behavior involving environment access, file reads/writes, and network activity, but it does not declare an explicit tool/permission scope. That creates an authorization ambiguity: a host may expose broader capabilities than the user expects, enabling data access or outbound requests outside the core claim-guidance function.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
third-party personal data (a bystander's email in a thread, for
example). Preserve claimant business and legal-entity information;
notices are legally required to contain it and it is core evidence.
Never redact the user's own information without asking first. The
livelihood-critical flag is session-scoped: it calibrates warnings in
the conversation and is never written into the organizer unless the
user asks for it there.
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
third-party personal data (a bystander's email in a thread, for
example). Preserve claimant business and legal-entity information;
notices are legally required to contain it and it is core evidence.
Never redact the user's own information without asking first. The
livelihood-critical flag is session-scoped: it calibrates warnings in
the conversation and is never written into the organizer unless the
user asks for it there.
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill encourages users to paste claim emails, screenshots, and optionally store claim state in memory, but it does not present a clear upfront user-facing warning that these materials may contain sensitive personal, financial, or legal information. In a copyright-dispute context, that omission increases the risk of oversharing notices, identifiers, account details, or privileged communications.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
read-back renders as two plain lists ("here's what I could read" and
"here's what I still need"), and nothing extracted enters the
organizer, the timeline, or any severity calculation until the user
confirms or corrects it. No confirmation, no continuation on that
data. PII handling per S-04 applies to everything shared, and the
question path below remains fully available at any moment, including
mid-parse.
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This is a markdown file, so SQP-2 applies to omissions of warnings about behaviors affecting privacy or legal exposure. Although the text states that contact information may be forwarded, it presents this as definitional glossary content rather than an explicit warning or caution to users before they act, despite the clear privacy and legal implications.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The manifest for content-claim-navigator says the skill should explain automated copyright-claim procedures, organize evidence, and provide platform-specific flow coverage, while explicitly limiting scope around related but distinct matters. This file instead adds a separate 'legal-help' capability focused on affordable counsel directories and EU DSA rights processes, which goes beyond procedural claim navigation and evidence organization.

External Transmission

Medium
Category
Data Exfiltration
Content
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
API_URL = "https://api.anthropic.com/v1/messages"
MODEL = os.environ.get("EVAL_MODEL", "claude-sonnet-4-6")
JUDGE_MODEL = os.environ.get("JUDGE_MODEL", "claude-opus-4-8")
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.