Security: CSV export has no formula injection prevention or documented risk acceptance [SEC-F12] #432
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#432
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
indexer/src/api/text_csv.rsimplements RFC 4180-compliant CSV escaping viacsv_escape_cell. The function quotes cells containing a comma, double-quote, newline, or leading/trailing space. It does not check for or escape leading=,+,-, or@characters, which spreadsheet clients (Excel, LibreOffice, Google Sheets) interpret as formula prefixes. The only CSV test (get_trader_trades_csv_returns_text_csvinindexer/tests/api_traders.rslines 165-186) checks content-type and header row field names only. No test asserts formula injection safety. No inline comment provides risk acceptance for the controlled-field argument.What Was Checked
indexer/src/api/text_csv.rslines 5-17:csv_escape_cellchecks comma, double-quote, newline, CR, leading/trailing space. No check for=,+,-,@prefix. Confirmed by full file read.trader_swaps_csv,trader_limit_fills_csv,trader_limit_cancellations_csv: numeric IDs (i64),terra1...addresses, hex tx hashes, ISO-8601 timestamps, denom strings (uluna, CW20 contract addresses),sideenum (bid/ask). None are free-text user inputs; none start with formula characters under normal chain operation.indexer/tests/api_traders.rslines 165-186: CSV test checkscontent-type: text/csvand that body contains header field names (id,pair_address,block_height,tx_hash). No formula injection test present. Confirmed by direct read.text_csv.rsorapi_traders.rsdocuments that fields are controlled and formula injection risk is accepted.Expected (per checklist)
Either: (a) a test asserts that a cell starting with
=is escaped or prefixed to neutralize formula interpretation, or (b) a documented comment states that all exported fields are controlled numeric/address/hash values that cannot originate from user-supplied free text, and no formula injection prefix is therefore required.Actual
No formula injection prefix prevention is implemented. No test asserts safety. No documented risk acceptance exists. The fields are controlled in practice (low risk), but the checklist requires one of the two verification forms and neither is present.
Evidence
indexer/src/api/text_csv.rsline 6:must_quotecondition covers comma, quote, newline, CR, space but notstarts_with('='),starts_with('+'),starts_with('-'), orstarts_with('@')indexer/tests/api_traders.rslines 165-186: CSV test asserts content-type and header row only, no formula injection assertiontext_csv.rsSuggested Fix
Add a comment to
csv_escape_cellintext_csv.rsstating that all exported fields originate from validated chain data (numeric IDs, terra1 addresses, hex hashes, ISO timestamps, controlled enums) and cannot begin with a formula character. Alternatively, add a unit test that constructs aTradeResponsewithoffer_assetset to"=HYPERLINK(...)"and asserts the CSV cell does not start with=(or that the cell is quoted in a way that neutralizes it).Verification Checklist
text_csv.rscontains a comment documenting that exported fields are controlled and cannot originate from user-supplied free text=,+,-,@values in a CSV cellLabels
security,pre-launchCc: @PlasticDigits
Option (a) accepted
mentioned in issue #381
mentioned in commit
c14c989fa1mentioned in merge request !960
mentioned in commit
6afbcb194fVerification — #432 SEC-F12 (CSV formula injection)
Result: PASS — Option (a) (formula-injection tests) is implemented on
main(merge6afbcb19, commitc14c989f).Acceptance checklist
text_csv.rsdocuments controlled fields or formula-injection testindexer/src/api/text_csv.rslines 5–6 document prefix neutralization; lines 118–182 add four unit tests.=,+,-,@cargo test --lib text_csv::tests— 4/4 passed:csv_escape_cell_neutralizes_bare_formula_prefix,csv_escape_cell_neutralizes_formula_prefixes(all four chars),csv_escape_cell_neutralizes_formula_prefix_with_commas,trader_swaps_csv_neutralizes_formula_in_offer_asset.csv_escape_cellprefixes=,+,-,@with'before RFC 4180 quoting (lines 7–12).Implementation summary
csv_escape_cellprepends'when a cell starts with=,+,-, or@.trader_swaps_csvwithoffer_asset = "=HYPERLINK(...)".docs/indexer-invariants.mdandskills/AGENTS_FRONTEND_ORDER_HISTORY.mdcross-link SEC-F12 / #432.Existing integration test (unchanged, still valid)
get_trader_trades_csv_returns_text_csvinindexer/tests/api_traders.rscontinues to asserttext/csvcontent-type and header row; formula safety is covered by the dedicated unit tests above.No repo changes required during this verification pass.
mentioned in issue #337
mentioned in issue #479
mentioned in merge request !1016
mentioned in issue #586
mentioned in issue #594