T09 · Insecure Skill Coding Practices
- Location
scripts/api_cost_tracker.py:362- Finding
Untrusted Model Names Permit Terminal and Markdown Report Injection
- Content
View full analysis
8} {format_tokens(stats['input_tokens']):>8} " f"{format_tokens(stats['output_tokens']):>8} {format_cost(stats['cost']):>10}") print() # Top expensive requests if args.top: sorted_entries = sorted(entries, key=lambda e: e.cost or 0, reverse=True)[:args.top] print(f" Top {args.top} Most Expensive Requests:") print(f" {'─' * 56}") for i, e in enumerate(sorted_entries, 1): ts = e.timestamp.strftime("%m-%d %H:%M") if hasattr(e.timestamp, 'strftime') else str(e.timestamp)[:16] model = normalize_model_name(e.model)[:20] print(f" {i:>3}. {ts} {model:<20} {format_tokens(e.input_tokens):>6}in " f"{format_tokens(e.output_tokens):>6}out {format_cost(e.cost or 0)}") ``` The same untrusted aggregation key is inserted directly into Markdown output: ```python for key, stats in groups.items(): print(f"| {key} | {stats['count']} | {format_tokens(stats['input_tokens'])} | " f"{format_tokens(stats['output_tokens'])} | {format_cost(stats['cost'])} |") ``` ### Technical Analysis Model names are read from user-supplied JSON or CSV usage files. They are passed through `normalize_model_name()`, but that function only lowercases and trims the value, removes selected provider prefixes and date suffixes, and resolves known aliases. It does not reject or escape: - ANSI terminal escape sequences - Control characters - Newline and carriage-return characters - Terminal hyperlink sequences - Markdown table delimiters such as `|` - Markdown formatting or embedded HTML The resulting attacker-controlled values are printed directly to terminal and Markdown reports. Formatti ...[truncated 1741 chars]- Remediation
View remediation
