DAG-CBOR doesn't reject non-string map keys — violates DAG-CBOR spec
- Dominant language
- Python
- Stars
- 13
- Forks
- 9
- PR merge metrics
- No merged PRs in 30d
Description
The DAG-CBOR specification requires all map keys to be strings. `_prepare_for_cbor()` passes through non-string keys without validation, producing invalid DAG-CBOR output.
### Problem
In `dag/codecs/dag_cbor.py`:
```python
def _prepare_for_cbor(node: Any) -> Any:
if is_cid(node):
cid_bytes = node.buffer
return cbor2.CBORTag(_CID_CBOR_TAG, _MULTIBASE_IDENTITY + cid_bytes)
if isinstance(node, dict):
return {k: _prepare_for_cbor(v) for k, v in node.items()}
# ← Non-string keys are passed through without validation
# ...
```
The [DAG-CBOR spec](https://ipld.io/specs/codecs/dag-cbor/spec/) states:
> "Map keys MUST be strings. No other types are allowed as map keys."
This means:
```python
# This should raise an error, but doesn't:
encode({1: "value"}) # Integer key — invalid
encode({(1, 2): "value"}) # Tuple key — invalid
encode({b"bytes": "value"}) # Bytes key — invalid
```
### Proposed Solution
Add validation in `_prepare_for_cbor()`:
```python
def _prepare_for_cbor(node: Any) -> Any:
if is_cid(node):
cid_bytes = node.buffer
return cbor2.CBORTag(_CID_CBOR_TAG, _MULTIBASE_IDENTITY + cid_bytes)
if isinstance(node, dict):
for k in node.keys():
if not isinstance(k, str):
raise ValueError(
f"DAG-CBOR map keys must be strings, got {type(k).__name__}: {k!r}"
)
return {k: _prepare_for_cbor(v) for k, v in node.items()}
# ...
```
Add tests verifying that non-string keys raise `ValueError`.
### Related
- DAG-CBOR spec: https://ipld.io/specs/codecs/dag-cbor/spec/
- File: `dag/codecs/dag_cbor.py`
Contributor guide
Research direction
Start in dag/codecs/dag_cbor.py and trace _prepare_for_cbor() through dictionary handling. Add coverage for integer, tuple, and bytes map keys, and verify that each raises ValueError while valid string-keyed maps still encode successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 85/100