GIScience / GIScience/ohsome-api
Stored CSV Formula Injection via OSM Tag Values
- Dominant language
- Python
- Stars
- 67
- Forks
- 10
- PR merge metrics
- No merged PRs in 30d
Description
## Bug Description
The CSV renderer writes OSM-derived tag values directly into CSV cells without neutralizing spreadsheet formula prefixes.
For grouped statistics responses, `tagvalue` is populated from OSM tag values. If a value begins with `=`, `+`, `-`, or `@`, it is emitted verbatim. Opening the downloaded CSV in Excel or LibreOffice may cause the value to be interpreted as a formula.
This is a CSV formula injection issue (CWE-1236).
## Affected Version / Endpoint
- Current `main` branch (v2 rewrite, checked out 2026-09-12)
- `src/ohsome_api/response_renderers.py`
- Example endpoint:
```text
POST /stats/features/{measure}.csv
```
with:
```json
{
"group_by": {
"type": "byTag",
"key": ""
}
}
```
## Reproduction
```python
from ohsome_api.response_renderers import CSVSnapshotsResponse
content = {
"result": [{
"timestamp": "2020-01-01T00:00:00Z",
"value": 5,
"tagvalue": "=1+1"
}]
}
print(CSVSnapshotsResponse(content).body.decode())
```
Output:
```text
timestamp;value;tagvalue
2020-01-01T00:00:00Z;5;=1+1
```
The formula prefix is preserved without escaping.
In a real request, `tagvalue` originates from OSM tag values stored in the database. An attacker-controlled OSM tag such as:
```text
example_tag = =1+1
```
can therefore appear in a grouped CSV response and be interpreted as a spreadsheet formula when opened.
## Expected Behaviour
String values beginning with spreadsheet formula prefixes such as `=`, `+`, `-`, or `@` should be neutralized before being written to CSV, for example by prefixing them with `'`.
## Suggested Fix
Sanitize string values before passing them to the CSV writer. For example:
```python
def sanitize_csv_value(value):
if isinstance(value, str) and value.startswith(("=", "+", "-", "@")):
return "'" + value
return value
```
This sanitization should preferably be applied centrally in the CSV rendering layer so that all data-derived string columns are protected.
## CWE
CWE-1236: Improper Neutralization of Formula Elements in a CSV File
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in src/ohsome_api/response_renderers.py, focusing on CSVSnapshotsResponse and the CSV rendering path used by POST /stats/features/{measure}.csv. Run the provided reproduction with a tagvalue beginning with =, then verify that formula-prefixed string values are neutralized in the generated CSV while ordinary values remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 86/100