Back to skill

Security audit

incident-postmortem

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent incident-report generator, but its HTML output can preserve executable markup from incident data or logs, which is risky for generated reports.

Install only if you are comfortable using it with trusted inputs or markdown/JSON output. Avoid opening generated HTML reports from untrusted incident files or logs until the HTML renderer escapes or sanitizes all user-controlled fields and the title.

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:383
Finding

Stored HTML and JavaScript 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
    `, ``, `<object>`, `<embed>`, and similar active elements. - Event-handler attributes such as `onclick`, `onerror`, and `onload`. - Dangerous URL schemes such as `javascript:` and unsafe `data:` URLs. - Unexpected SVG or MathML elements and attributes. 4. Construct the document title from an escaped value: ```python import html safe_title = html.escape(str(title), quote=True) ``` 5. Treat log messages as plain text rather than markup, because logs commonly contain attacker-controlled request data. 6. Consider adding a restrictive Content Security Policy to generated reports as defense in depth: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:"> ``` This should supplement output encoding and sanitization, not replace them. 7. Add regression tests covering payloads in every input channel, including: - Incident titles and summaries. - Timeline event text. - Action-item table cells. - Parsed log messages. - Closing-tag payloads such as `</title>`. - Event handlers and dangerous URL schemes. The tests should verify that payloads appear only as encoded text and cannot create executable DOM elements or attributes. ]]>
    Vulnerability Patterns
    • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
    • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
    • 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)

    Undeclared Tool Scope

    Medium
    Category
    MCP Least Privilege
    Confidence
    91% confidence
    Finding

    The skill documents behaviors that imply filesystem read/write access (--log, --timeline, --from, -o, --check-blame) and potentially network-capable code according to the analyzer, but it does not declare any explicit tool scope or permission boundaries. Undeclared capabilities make it harder for the runtime or reviewer to enforce least privilege, increasing the risk of overbroad file access, unsafe output writes, or unexpected external communication if the backing script supports it.

    Content

    No source excerpt is available for this finding.

    Natural-Language Policy Violations

    Low
    Category
    Not specified by scanner
    Confidence
    84% confidence
    Finding

    The HTML template sets unconditionally, which imposes a specific language/locale choice in generated output. The file does not provide any option for users to select another language or document why English is required.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Low
    Category
    Not specified by scanner
    Confidence
    93% confidence
    Finding

    This code creates parent directories and writes report content to the path supplied by --out, which is a file-system modifying operation. While the behavior is part of report generation, there is no confirmation prompt and no explicit disclosure near the write path that the script will create directories and write a file rather than only printing to stdout.

    Content

    No source excerpt is available for this finding.