T09 · Insecure Skill Coding Practices
- Location
scripts/elderly_assistant.py:508- Finding
Unescaped User Input Enables Script Injection in Generated HTML
- Content
View full analysis
Vulnerability Details
File Location:
scripts/elderly_assistant.py, lines 508, 845, and 870–872; related command-line input sources at lines 924 and 942
Vulnerability Type: HTML injection and cross-site scripting in generated reports
Risk Level: HighVulnerable Code
The dashboard inserts the user-supplied name directly into an HTML document:
python <div style="text-align:center;font-size:24px;margin:16px 0;"> 👋 {user_name},今天有什么我能帮您的? </div>The health report inserts the supplied health concern without HTML escaping:
python <div class="card"> <p><strong>您提到:</strong>{concern}</p> </div>Medication fields are likewise inserted directly into table cells:
python for i, med in enumerate(medications, 1): rows += f''' <tr> <td style="padding:12px;border-bottom:1px solid #ddd;">{i}</td> <td style="padding:12px;border-bottom:1px solid #ddd;font-weight:bold;">{med.get('name', '')}</td> <td style="padding:12px;border-bottom:1px solid #ddd;">{med.get('dosage', '')}</td> <td style="padding:12px;border-bottom:1px solid #ddd;color:#ff6b35;font-weight:bold;">{med.get('time', '')}</td> </tr>'''Two affected values can be supplied directly through command-line arguments:
python name = sys.argv[2] if len(sys.argv) > 2 else "叔叔/阿姨"python concern = sys.argv[2] if len(sys.argv) > 2 else ""Technical Analysis
The HTML generation functions use Python formatted strings to concatenate untrusted values into HTML text contexts. No encoding, sanitization, validation, or restrictive Content Security Policy is applied.
An input containing active markup, such as:
html <img src=x onerror="alert(document.domain)">is retained as an HTML element rather than displayed as plain text. When the generated report is saved and presented in an HTML-capable browser or viewer, the event handler can execute JavaScript.
The affected entry points and sinks are:
user_namepassed t ...[truncated 2479 chars]
- Remediation
View remediation
Remediation Suggestions
-
Escape every untrusted value before inserting it into HTML:
python from html import escape safe_user_name = escape(str(user_name), quote=True) safe_concern = escape(str(concern), quote=True) safe_name = escape(str(med.get("name", "")), quote=True) safe_dosage = escape(str(med.get("dosage", "")), quote=True) safe_time = escape(str(med.get("time", "")), quote=True) -
Use only the escaped variables in generated markup.
-
Prefer an established template engine with automatic HTML escaping enabled rather than constructing documents through formatted strings.
-
Validate input types, lengths, and allowed characters. Medication schedule entries should be required to be dictionaries containing bounded text values.
-
Add a restrictive Content Security Policy to generated pages, for example:
html <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; script-src 'none';">The dashboard currently requires inline JavaScript, so it should instead move scripts into a trusted external resource with a hash or nonce-based policy. Report pages that need no JavaScript should use
script-src 'none'. -
Add regression tests covering payloads with script tags, event-handler attributes, malformed elements, encoded markup, quotation marks, and closing tags. Tests should verify that these values appear as text and never become DOM elements.
-
Treat all values returned by an AI model, read from user files, or supplied by command-line arguments as untrusted, even when the expected content is a name, symptom, dosage, or time.
-
