ipld / ipld/py-ipld-dag

DAG-CBOR doesn't reject non-string map keys — violates DAG-CBOR spec

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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.