T09 · Insecure Skill Coding Practices
- Location
scripts/frisbee_chart.py:297- Finding
Unescaped Garmin and User-Controlled Values Permit Script Injection in Generated Dashboards
- Content
View full analysis
No activities found in this date range." rows = "" for i, a in enumerate(activities, 1): dur = int((a.get("duration_seconds") or 0) // 60) hrr_count = len(a.get("hrr", [])) hrr_note = f"✓ {hrr_count} pts" if hrr_count else "—" rows += f""" Game {i} {a.get('date', '—')} {a.get('activity_name', '—')} {a.get('activity_type', '—')} {dur} min {a.get('avg_hr') or '—'} {a.get('max_hr') or '—'} {a.get('calories') or '—'} {hrr_note} """ ``` ```python def generate_tournament_html(data): name = data.get("name", "Tournament") start = data.get("start_date", "") end = data.get("end_date", "") title = f"{name} | {start} → {end}" ... charts_json = json.dumps({"stats": stats, "charts": charts}) return f""" ... {title} ...{a['date']} {a['name'][:20]} {a.get('category','—')} {a['dur ...[truncated 2149 chars]🥏 {name}
{start} → {end} · Generated {generated}... {activity_table} ``` The comparison dashboard contains the same class of issue: ```python table_rows = "" for a in all_relevant: table_rows += f"""- Remediation
View remediation
` element and read it using `textContent`, while escaping `<`, `>`, `&`, U+2028, and U+2029. 4. Alternatively, serialize data to a separate local JSON file and parse it as data rather than executable source. 5. Add a restrictive Content Security Policy that disallows inline event handlers and limits outbound connections. 6. Add regression tests using values containing ``, ``, quotes, ampersands, and Unicode line separators. ]]>
