T09 · Insecure Skill Coding Practices
- Location
scripts/parse.py:42- Finding
Attacker-Controlled Log Content Can Break Out of Markdown Code Fences
- Content
View full analysis
Vulnerability Details
File Location:
scripts/parse.py:42-49
Vulnerability Type: Improper neutralization of untrusted content in generated Markdown
Risk Level: MediumVulnerable Code
python def to_markdown_alerts(rules): lines = ["# Alert Rules\n"] for r in rules: lines.append(f"## {r['name']} (`{r['type']}`)\n") lines.append(f"- **Severity:** {r['severity']}") lines.append(f"- **Occurrences:** {r['count']}") lines.append(f"- **Regex:** ````{r['pattern']}````") lines.append(f"- **Samples:**") for s in r["top_samples"]: lines.append(f" ```\n {s}\n ```")Technical Analysis
Log samples are attacker-controlled data and are inserted verbatim into Markdown code fences. The implementation neither escapes backtick sequences nor selects a fence longer than those appearing in the sample.
The parser separates records only on the line-feed character:
python lines = [l.strip() for l in log_text.split("\n") if l.strip()]Consequently, a record containing carriage-return-only separators can remain a single Python string while being interpreted as multiple lines by Markdown processors that normalize carriage returns. Such content can include a valid closing fence followed by attacker-controlled Markdown.
Even when the generated report is not rendered, passing it to another AI Agent without preserving the trust boundary can turn injected report text into indirect prompt-injection content. The parser itself does not execute the injected content.
Attack Path
- An attacker causes a server log to contain a record with a recognized term such as
error. - The record uses carriage-return-only separators and includes a closing Markdown fence followed by attacker-controlled Markdown or instructions.
extract_patterns()retains the record as a sample becausesplit("\n")does not divide it at carriage ret ...[truncated 787 chars]
- An attacker causes a server log to contain a record with a recognized term such as
- Remediation
View remediation
Remediation Suggestions
- Normalize all supported line endings before parsing, for example with
splitlines(). - Escape or replace backtick runs in untrusted samples before Markdown serialization.
- Alternatively, calculate the longest backtick run in each sample and use a strictly longer fence.
- Consider encoding samples as indented code blocks or structured JSON rather than interpolating them into Markdown.
- Clearly label all extracted samples as untrusted input.
- Do not pass generated reports to an AI Agent as trusted instructions; isolate samples in a data-only channel where available.
- Add tests covering triple backticks, carriage-return-only logs, mixed line endings, Markdown links, and Agent-instruction-like content.
- Normalize all supported line endings before parsing, for example with
