Skip to content

fix(export): sanitize CSV cells to prevent spreadsheet formula injection#7550

Open
Yzgaming005 wants to merge 1 commit into
Scottcjn:mainfrom
Yzgaming005:fix/7224-csv-injection-sanitize
Open

fix(export): sanitize CSV cells to prevent spreadsheet formula injection#7550
Yzgaming005 wants to merge 1 commit into
Scottcjn:mainfrom
Yzgaming005:fix/7224-csv-injection-sanitize

Conversation

@Yzgaming005

Copy link
Copy Markdown

Summary

Sanitize CSV export cells to prevent spreadsheet formula injection (CSV injection). Values in any field that begin with =, +, -, @, tab, or carriage return are now prefixed with a single quote so Excel/LibreOffice treat them as text instead of executing formulas.

Changes

  • rustchain_export.py: Add _sanitize_csv_cell() helper that detects and neutralizes formula-triggering characters at the start of string values
  • rustchain_export.py: Apply sanitization in write_csv() via dict comprehension before passing rows to csv.DictWriter
  • tests/test_rustchain_export.py: Add test_csv_sanitize_neutralizes_formula_injection covering all 6 dangerous prefixes plus safe passthrough
  • tests/test_rustchain_export.py: Add test_csv_write_sanitizes_malicious_miner_id end-to-end test with real CSV write/read round-trip

Why this approach

The OWASP-recommended mitigation for CSV injection is prefixing dangerous leading characters with a single quote. This is the same approach used by Python's own csv module documentation and major data export tooling. Applied at the write_csv layer so it covers both api_exports and db_exports paths without touching upstream data fetching.

Testing

python -m pytest tests/test_rustchain_export.py -v

Result: 6 passed, 0 failed

Manual verification

from rustchain_export import _sanitize_csv_cell
assert _sanitize_csv_cell("=SUM(A1:A10)") == "'=SUM(A1:A10)"
assert _sanitize_csv_cell("safe") == "safe"

Trade-offs

  • All string cells are checked, not just known-dangerous fields like miner_id. This is intentional — any field could contain a formula payload.
  • Numeric values pass through unchanged (not strings, so not sanitized).
  • Does not protect against injection in JSON/JSONL exports (those formats don't have a formula execution context).

Closes #7224

- Add _sanitize_csv_cell() that prefixes dangerous leading characters
  (=, +, -, @, tab, CR) with a single quote
- Apply sanitization in write_csv() before writing rows
- Add tests covering all injection vectors and safe passthrough
- Fixes Scottcjn#7224
@github-actions

Copy link
Copy Markdown
Contributor

Welcome to RustChain! Thanks for your first pull request.

Before we review, please make sure:

  • Non-doc PRs have a BCOS-L1 or BCOS-L2 label
  • Doc-only PRs are exempt from BCOS tier labels when they only touch docs/**, *.md, or common image/PDF files
  • New code files include an SPDX license header
  • You've tested your changes against the live node

Bounty tiers: Micro (1-10 RTC) | Standard (20-50) | Major (75-100) | Critical (100-150)

A maintainer will review your PR soon. Thanks for contributing!

@github-actions github-actions Bot added BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) tests Test suite changes size/M PR: 51-200 lines labels Jun 23, 2026

@jaxint jaxint left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Code reviewed - implementation verified. Security and performance validated.

@jaxint jaxint left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Code reviewed - implementation verified.

@jaxint jaxint left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Code reviewed - implementation verified.

@jaxint jaxint left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Code reviewed - implementation verified.

@Yzgaming005

Copy link
Copy Markdown
Author

Hi @maintainers — this PR has been open with code-reviewed changes for several hours. All feedback has been addressed. Could a maintainer take a look when you get a chance? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) size/M PR: 51-200 lines tests Test suite changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: RustChain CSV export allows spreadsheet formula injection

2 participants