T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/generate_excel.py:91
- Finding
- Spreadsheet Formula Injection Through Student Names<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_excel.py`, lines 91 and 181–189 **Vulnerability Type**: Spreadsheet formula injection **Risk Level**: High ### Vulnerable Code ```python for row, student in enumerate(stats['students'], 2): ws_students.cell(row=row, column=1, value=student['name']) ws_students.cell(row=row, column=2, value=student['correct_count']) ws_students.cell(row=row, column=3, value=student['incorrect_count']) ws_students.cell(row=row, column=4, value=f"{student['error_rate']}%") ws_students.cell(row=row, column=5, value=str(student['incorrect_questions'])) ``` The student records are loaded from an externally supplied JSON file without validation: ```python with open(student_file, 'r', encoding='utf-8') as f: students_data = json.load(f) with open(correct_file, 'r', encoding='utf-8') as f: correct_answers = json.load(f) generate_excel(students_data, correct_answers, output_path, threshold) ``` ### Technical Analysis The `name` field is controlled by the supplied student-data JSON and is passed directly to `openpyxl` as a cell value. A string beginning with `=` can be stored as a spreadsheet formula instead of inert text. Formula-like prefixes such as `+`, `-`, or `@` may also receive special treatment in some spreadsheet applications or workflows. No validation or neutralization is applied before the workbook is saved. An attacker able to influence a student name could therefore inject a formula such as a hyperlink, an external-data function, or another application-supported formula. Execution occurs when a teacher or administrator opens or interacts with the generated workbook, subject to the spreadsheet application's security policy. ### Attack Path 1. An attacker supplies or influences a student-data JSON record. 2. The attacker sets the `name` field to a formula-like value, for example one beginning with `=`. 3. `generate_excel.py` loads the JSON without validating the fie ...[truncated 1100 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Treat all values originating from OCR, JSON input, student names, and answer data as untrusted. - Before writing text to a workbook, neutralize values beginning with `=`, `+`, `-`, or `@`. - Prefix formula-like values with an apostrophe or explicitly force the cell to contain an inert string. - Centralize this protection in a helper and apply it to every user-controlled cell. Example: ```python def safe_excel_text(value): text = str(value) if text.startswith(("=", "+", "-", "@")): return "'" + text return text cell = ws_students.cell( row=row, column=1, value=safe_excel_text(student["name"]) ) cell.data_type = "s" ``` - Define maximum field lengths and allowed character rules for names. - Add tests covering formula prefixes, leading whitespace, tabs, carriage returns, and Unicode variants. - Warn users not to disable spreadsheet protected-view or external-content protections. ]]>
