GIScience / GIScience/ohsome-api

Stored CSV Formula Injection via OSM Tag Values

Open Beginner friendly
#350 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.