Back to skill

Security audit

Incident Postmortem Generator

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but HTML reports can execute script hidden in incident data or logs.

Review before installing if you plan to generate HTML from logs or incident JSON that may contain untrusted content. Markdown and JSON output are less likely to execute browser script, but HTML reports should be treated as unsafe unless inputs are trusted or the generator is fixed to escape/sanitize content.

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/generate_postmortem.py:398
Finding

Stored HTML and Script Injection in Generated Reports

Content
View full analysis
\1', html, flags=re.MULTILINE) html = re.sub(r'^## (.+)$', r'

\1

', html, flags=re.MULTILINE) html = re.sub(r'^### (.+)$', r'

\1

', html, flags=re.MULTILINE) # Bold html = re.sub(r'\*\*(.+?)\*\*', r'\1', html) # Italic html = re.sub(r'_(.+?)_', r'\1', html) # Code html = re.sub(r'`(.+?)`', r'\1', html) # Lists html = re.sub(r'^- (.+)$', r'
  • \1
  • ', html, flags=re.MULTILINE) # Tables (simple conversion) def convert_table(match): lines = match.group(0).strip().split('\n') rows = [] for i, line in enumerate(lines): if '---' in line: continue cells = [c.strip() for c in line.strip('|').split('|')] tag = 'th' if i == 0 else 'td' row = ''.join(f'<{tag}>{c}' for c in cells) rows.append(f'{row}') return f'{"".join(rows)}
    ' html = re.sub(r'(\|.+\|(?:\n\|.+\|)*)', convert_table, html) # Paragraphs (lines not already wrapped) lines = html.split('\n') processed = [] for line in lines: if line.strip() and not line.strip().startswith('<') and not line.strip().startswith('*'): processed.append(f'

    {line}

    ') else: processed.append(line) html = '\n'.join(processed) return f"""
    Remediation
    View remediation
    ` value separately and always escape it before interpolation. 5. Add a restrictive Content Security Policy, such as a policy that disallows scripts and plugins, as defense in depth. Sanitization and escaping must remain the primary controls. 6. Add regression tests covering: - `` - `` - `` - `javascript:` URLs - Payloads in titles, summaries, timeline events, action items, and log messages 7. Document that input logs and JSON files may be untrusted and that generated HTML must not be published until sanitization is implemented. ]]>
    Vulnerability Patterns
    • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
    • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
    • 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 (2)

    Undeclared Tool Scope

    Medium
    Category
    MCP Least Privilege
    Confidence
    93% confidence
    Finding

    The skill documentation instructs use of local log files, output file generation, and references loading incident data from JSON, which implies file read/write capabilities, yet the skill declares no explicit tool scope such as permissions or allowed-tools. This creates an authorization gap where an agent may infer broader filesystem or network access than intended, increasing the risk of over-privileged execution or unsafe handling of sensitive incident data.

    Content

    No source excerpt is available for this finding.

    Natural-Language Policy Violations

    Low
    Category
    Not specified by scanner
    Confidence
    94% confidence
    Finding

    The generated HTML always sets <html lang="en">, which forces an English locale regardless of the incident content or user preference. This is a natural-language locale constraint in the file and there is no visible option for users to choose or override the language.

    Content

    No source excerpt is available for this finding.

    Static analysis

    No suspicious patterns detected.