T09 · Insecure Skill Coding Practices
- Location
scripts/download_transactions.py:253- Finding
Spreadsheet Formula Injection in Standalone Transaction CSV Export
- Content
View full analysis
Vulnerability Details
File Location:
scripts/download_transactions.py:253-278
Vulnerability Type: CSV/spreadsheet formula injection
Risk Level: Mediumpython with open(output_file, 'w', newline='', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction='ignore') writer.writeheader() for tx in transactions: # Extract amount betrag_obj = tx.get('betrag', {}) betrag = betrag_obj.get('amount', '') if isinstance(betrag_obj, dict) else betrag_obj waehrung = betrag_obj.get('currency', '') if isinstance(betrag_obj, dict) else 'EUR' row = { 'id': tx.get('id', ''), 'buchungstag': tx.get('buchungstag', ''), 'valuta': tx.get('valuta', ''), 'betrag': betrag, 'waehrung': waehrung, 'transaktionsteilnehmer': tx.get('transaktionsteilnehmerZeile1', ''), 'verwendungszweck': tx.get('verwendungszweckZeile1', ''), 'zahlungsreferenz': tx.get('zahlungsreferenz', ''), 'kategorieCode': tx.get('kategorieCode', ''), 'iban': tx.get('iban', ''), 'auftraggeberIban': tx.get('auftraggeberIban', ''), 'auftraggeberBic': tx.get('auftraggeberBic', ''), 'bestandreferenz': tx.get('bestandreferenz', ''), 'ersterfasserreferenz': tx.get('ersterfasserreferenz', '') } writer.writerow(row)Technical Analysis
The standalone transaction exporter copies fields returned by the banking API directly into CSV cells. These fields include counterparty names, payment purposes, references, and other transaction metadata that can originate from another banking participant.
csv.DictWritercorrectly quotes and delimits CSV fields, but CSV quoting does not prevent spreadsheet applications from interpreting cell values beginning with formula indicators such as=,+,-, or@. No formula-neutralization ste ...[truncated 1323 chars]- Remediation
View remediation
Remediation Suggestions
Introduce a shared CSV-cell sanitization function and apply it to every externally sourced textual field before serialization.
For example:
python def sanitize_csv_cell(value): if value is None: return "" text = str(value) if text.startswith(("=", "+", "-", "@", "\t", "\r")): return "'" + text return textApply this function to counterparty names, payment purposes, references, IBAN-related text, descriptions, and any other string originating from the API.
Additional hardening should include:
- Centralizing CSV sanitization so every export path uses the same policy.
- Sanitizing after canonicalization but immediately before CSV serialization.
- Adding tests for values beginning with
=,+,-,@, tab, and carriage return. - Documenting that CSV exports are intended to be safe for opening in common spreadsheet applications.
