T09 · Insecure Skill Coding Practices
- Location
scripts/generate_exam.py:57- Finding
Excel Formula Injection Through Untrusted Question Data
- Content
View full analysis
Vulnerability Details
File Location:
scripts/generate_exam.py, lines 57–65
Vulnerability Type: Excel formula injection
Risk Level: MediumVulnerable Code
python ws.cell(row=row, column=1, value=question.get('题型', '')).border = thin_border ws.cell(row=row, column=2, value=question.get('题目', '')).border = thin_border ws.cell(row=row, column=3, value=question.get('选项1', '')).border = thin_border ws.cell(row=row, column=4, value=question.get('选项2', '')).border = thin_border ws.cell(row=row, column=5, value=question.get('选项3', '')).border = thin_border ws.cell(row=row, column=6, value=question.get('选项4', '')).border = thin_border ws.cell(row=row, column=7, value=question.get('正确答案', '')).border = thin_border ws.cell(row=row, column=8, value=question.get('解析', '')).border = thin_border ws.cell(row=row, column=9, value=question.get('出处', '')).border = thin_borderTechnical Analysis
The script writes question data directly into XLSX cells without distinguishing trusted content from attacker-controlled text. The data can originate from the command-line JSON argument or from text derived from an uploaded flowchart.
In particular,
openpyxltreats a string beginning with=as a spreadsheet formula. Consequently, an attacker can place a formula in any exported field, including the question, options, explanation, source, or question type. The generated workbook then contains executable spreadsheet formula content rather than inert text.Depending on the spreadsheet application and its security settings, malicious formulas may initiate external requests, expose workbook content through attacker-controlled URLs, manipulate displayed data, or invoke other application-specific formula behavior. External-link warnings or protected-view controls may reduce exploitability, but they do not remove the unsafe data flow.
Attack Path
- An attacker supplies crafted flowchart content or a JSON ques ...[truncated 1291 chars]
- Remediation
View remediation
Remediation Suggestions
- Introduce one centralized function that converts all untrusted cell values to safe text before writing them.
- Neutralize values beginning with
=by prefixing an apostrophe or otherwise forcing the cell to be stored as a literal string. For defense in depth and compatibility with spreadsheet import behavior, also reject or neutralize leading+,-, and@characters. - Apply the sanitization function to every user-controlled field, including question type, question text, all options, answer, explanation, and source.
- Normalize leading whitespace and control characters before checking the first meaningful character, since they can be used to bypass simplistic validation.
- Validate the input schema: require a list of dictionaries, enforce string and length constraints, restrict question types and answers to approved values, and reject unexpected fields or nested objects.
- Add automated tests confirming that formula-like input is exported as visible literal text and that the resulting XLSX cell is not marked as a formula.
- Document that generated workbooks should be opened with external links and active content disabled.
Example hardening approach:
python def safe_excel_text(value): if value is None: return '' text = str(value) normalized = text.lstrip() if normalized.startswith(('=', '+', '-', '@')): return "'" + text return textUse
safe_excel_text()for every untrusted value supplied tows.cell().
