fix(repo): spec-correct MST and hardened DAG-CBOR / CAR parsing #111
Labels
No labels
breaking-change
bug
documentation
duplicate
enhancement
good first issue
help wanted
performance
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/ATProto.NET#111
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?
Part of the v0.7.0 update cycle. The MST does not follow the atproto spec, and the DAG-CBOR/CAR readers can be crashed by untrusted input. Both run on relay data.
Correctness: MST
Today every MST root CID differs from the network's (0/5 reference vectors match), so repos written by the SDK (#40:
MerkleSearchTree+RepoCommit+CarWriter) are rejected by other implementations.landtas explicit CBORnull, not omitted. The empty tree must hash tobafyreie5737gdxlw5i64vzichcalba3z2v5n6icifvx5xytvske7mr3hpm.nulll/t.MerkleSearchTree.Deserializecurrently throws on every realgetReponode.null, not an empty node.Add/Deletecurrently disagree with the bulk build in 99 of 100 random trials. Rebuild from the sorted entry set, or fix the mutation code, so that any sequence of edits yields the bulk-build root.bluesky-social/atprotopackages/repo/tests/mst.test.ts, plusatproto-interop-testsMST fixtures where they exist), and add a randomized add/delete ≡ bulk-build property test.Security: untrusted input
PrefixLen: validate0 ≤ p ≤ previousKey.Lengthwhile decoding and throwFormatException(same bug class as indigo's SEC-4 fix, 2026-09-02). Today a crafted node allocatesnew byte[p + …]withp ≈ 2^31before any check.CarReaderstack overflow: its hand-written recursive CBOR skipper for the CAR header crashes the process on a ~100 KB header of nested arrays (reproduced). Replace it withSystem.Formats.Cbor.CborReader.DagCborDecoder,FirehoseEventParser's transcoder), which overflow at the same depth.CarReadermust reject CIDv0 blocks, which currently bypass its unknown-codec rule.Consolidation (while touching these files)
DagCborLinkread/write helper replacing the 4 write and 4 read copies (CarWriter,MstNodeData,RepoCommit,DagCborEncoder/DagCborDecoder,FirehoseEventParser,CarReader).DagCborDecoder.DecodeandFirehoseEventParser, replacing theJsonNodetree plus re-serialize path (4.3→3.5 µs, 11.4→7.9 KB per record).DagCborEncoder: stop sorting keys twice (own sort plusCborConformanceMode.Canonical); assert byte-identical output.SpaceRepoCar.Serializewrites the index map directly withCborWriterinstead ofJsonObject→JsonElement→CBOR.ComputeNodeCidvsSerializeNode,Create(entries)vsCreateFromEntries,ValidateNode(make it rebuild-and-compare),DagCborDecoder.DecodeToNode,DagCborEncoder.ComputeCid, unused locals, andCarBlock.DataLength.MstNodeData,MstTreeEntryandMstKeyDepthinternal. Keep the documentedCidComputation.TryDecodeCidStringandTid.FromInt64/ToInt64.Acceptance
p, negativep, CIDv0) fail withFormatException, never crash.Fixedfor the MST,Securityfor the parsers,Breaking changesfor anything made internal or removed.