T09 · Insecure Skill Coding Practices
- Location
scripts/mdcal.py:59- Finding
Stored Calendar Event Injection Through Unescaped Event Fields
- Content
View full analysis
Vulnerability Details
File Location:
scripts/mdcal.py, lines 59-68; attacker-controlled values originate at lines 92-108
Vulnerability Type: Stored Markdown record injection
Risk Level: MediumVulnerable Code
python def write_markdown_events(filepath: Path, events: list): """将事件写回 Markdown 文件""" lines = ['# 日历\n', '## 事件\n'] # 按日期和时间排序 sorted_events = sorted(events, key=lambda e: (e['date'], e['time'])) for e in sorted_events: done = 'x' if e.get('done') else ' ' title = e.get('title', '无标题') desc = f" :: {e['desc']}" if e.get('desc') else '' eid = f" #{e['id']}" if e.get('id') else '' line = f"- [{done}] {e['date']} {e['time']} {title}{desc}{eid}\n" lines.append(line) filepath.write_text(''.join(lines), encoding='utf-8')The untrusted values are accepted and stored without validation:
python events.append({ 'date': date, 'time': time, 'title': title, 'desc': desc, 'done': False, 'id': id, })Technical Analysis
The application uses a line-oriented Markdown format as its event database. The event title and description are inserted directly into that format without rejecting or escaping carriage returns, newline characters, or reserved record delimiters.
An attacker who can control a title or description can include a newline followed by another syntactically valid event record. When the file is subsequently read,
parse_markdown_events()processes the injected line as an independent event. This is a stored injection issue because the malicious record persists in the monthly Markdown file and affects later commands.The generated event identifier protects only the legitimate record. It does not prevent injected content from supplying a separate attacker-selected five-character identifier matching the parser's
#(\w{5})requirement.Attack Path
...[truncated 1239 chars]
- Remediation
View remediation
Remediation Suggestions
- Reject
\rand\nin all fields stored in the line-oriented Markdown format. - Validate the title and description before modifying any calendar file.
- Define maximum field lengths to limit malformed or excessively large records.
- Escape or reject reserved syntax such as
::and trailing identifier patterns when these delimiters can alter parsing behavior. - Prefer a structured storage format such as JSON with schema validation, generating Markdown only as a display format.
- When parsing existing files, verify that dates belong to the expected monthly file and that identifiers satisfy the exact intended format.
- Add tests covering embedded newlines, carriage returns, delimiter sequences, attacker-selected identifiers, and malformed records.
- Reject
