SkillAgentSearch skills...

Cbor

CBOR codec (RFC 8949, RFC 8742) with CBOR tags, Go struct tag options (toarray, keyasint, omitempty, omitzero), float64/32/16, big.Int, and fuzz tested.

Install / Use

/learn @fxamacker/Cbor

README

<h1>CBOR Codec <a href="https://pkg.go.dev/github.com/fxamacker/cbor/v2"><img src="https://raw.githubusercontent.com/fxamacker/images/refs/heads/master/cbor/go-logo-blue.svg" alt="Go logo" style="height: 1em;" align="right"></a></h1>

fxamacker/cbor is a library for encoding and decoding CBOR and CBOR Sequences.

CBOR is a trusted alternative to JSON, MessagePack, Protocol Buffers, etc.  CBOR is an Internet Standard defined by IETF STD 94 (RFC 8949) and is designed to be relevant for decades.

fxamacker/cbor is used in projects by Arm Ltd., EdgeX Foundry, Flow Foundation, Fraunhofer‑AISEC, IBM, Kubernetes*, Let's Encrypt, Linux Foundation, Microsoft, Oasis Protocol, Red Hat*, Tailscale*, Veraison*, etc.

See Quick Start and Releases. 🆕 UnmarshalFirst and DiagnoseFirst can decode CBOR Sequences. MarshalToBuffer and UserBufferEncMode accepts user-specified buffer.

fxamacker/cbor

CodeQL Go Report Card

fxamacker/cbor is a CBOR codec in full conformance with IETF STD 94 (RFC 8949). It also supports CBOR Sequences (RFC 8742) and Extended Diagnostic Notation (Appendix G of RFC 8610).

Features include full support for CBOR tags, Core Deterministic Encoding, duplicate map key detection, etc.

API is mostly same as encoding/json, plus interfaces that simplify concurrency and CBOR options.

Design balances trade-offs between security, speed, concurrency, encoded data size, usability, etc.

<details><summary> 🔎&nbsp; Highlights</summary><p/>

🚀  Speed

Encoding and decoding is fast without using Go's unsafe package. Slower settings are opt-in. Default limits allow very fast and memory efficient rejection of malformed CBOR data.

🔒  Security

Decoder has configurable limits that defend against malicious inputs. Duplicate map key detection is supported. By contrast, encoding/gob is not designed to be hardened against adversarial inputs.

Codec passed multiple confidential security assessments in 2022. No vulnerabilities found in subset of codec in a nonconfidential security assessment prepared by NCC Group for Microsoft Corporation.

🗜️  Data Size

Struct tag options (toarray, keyasint, omitempty, omitzero) and field tag "-" automatically reduce size of encoded structs. Encoding optionally shrinks float64→32→16 when values fit.

:jigsaw:  Usability

API is mostly same as encoding/json plus interfaces that simplify concurrency for CBOR options. Encoding and decoding modes can be created at startup and reused by any goroutines.

Presets include Core Deterministic Encoding, Preferred Serialization, CTAP2 Canonical CBOR, etc.

📆  Extensibility

Features include CBOR extension points (e.g. CBOR tags) and extensive settings. API has interfaces that allow users to create custom encoding and decoding without modifying this library.

<hr/> </details>

Secure Decoding with Configurable Settings

fxamacker/cbor has configurable limits, etc. that defend against malicious CBOR data.

Notably, fxamacker/cbor is fast at rejecting malformed CBOR data.

[!NOTE]
Benchmarks rejecting 10 bytes of malicious CBOR data decoding to []byte:

| Codec | Speed (ns/op) | Memory | Allocs | | :---- | ------------: | -----: | -----: | | fxamacker/cbor 2.7.0 | 47 ± 7% | 32 B/op | 2 allocs/op | | ugorji/go 1.2.12 | 5878187 ± 3% | 67111556 B/op | 13 allocs/op |

Faster hardware (overclocked DDR4 or DDR5) can reduce speed difference.

<details><summary> 🔎&nbsp; Benchmark details </summary><p/>

Latest comparison for decoding CBOR data to Go []byte:

  • Input: []byte{0x9B, 0x00, 0x00, 0x42, 0xFA, 0x42, 0xFA, 0x42, 0xFA, 0x42}
  • go1.22.7, linux/amd64, i5-13600K (DDR4-2933, disabled e-cores)
  • go test -bench=. -benchmem -count=20

Prior comparisons

| Codec | Speed (ns/op) | Memory | Allocs | | :---- | ------------: | -----: | -----: | | fxamacker/cbor 2.5.0-beta2 | 44.33 ± 2% | 32 B/op | 2 allocs/op | | fxamacker/cbor 0.1.0 - 2.4.0 | ~44.68 ± 6% | 32 B/op | 2 allocs/op | | ugorji/go 1.2.10 | 5524792.50 ± 3% | 67110491 B/op | 12 allocs/op | | ugorji/go 1.1.0 - 1.2.6 | 💥 runtime: | out of memory: | cannot allocate |

  • Input: []byte{0x9B, 0x00, 0x00, 0x42, 0xFA, 0x42, 0xFA, 0x42, 0xFA, 0x42}
  • go1.19.6, linux/amd64, i5-13600K (DDR4)
  • go test -bench=. -benchmem -count=20
</details>

In contrast, some codecs can crash or use excessive resources while decoding bad data.

[!WARNING]
Go's encoding/gob is not designed to be hardened against adversarial inputs.

<details><summary> 🔎&nbsp; gob fatal error (out of memory) 💥 decoding 181 bytes</summary><p/>
// Example of encoding/gob having "fatal error: runtime: out of memory"
// while decoding 181 bytes (all Go versions as of Dec. 8, 2024).
package main
import (
	"bytes"
	"encoding/gob"
	"encoding/hex"
	"fmt"
)

// Example data is from https://github.com/golang/go/issues/24446
// (shortened to 181 bytes).
const data = "4dffb503010102303001ff30000109010130010800010130010800010130" +
	"01ffb80001014a01ffb60001014b01ff860001013001ff860001013001ff" +
	"860001013001ff860001013001ffb80000001eff850401010e3030303030" +
	"30303030303030303001ff3000010c0104000016ffb70201010830303030" +
	"3030303001ff3000010c000030ffb6040405fcff00303030303030303030" +
	"303030303030303030303030303030303030303030303030303030303030" +
	"30"

type X struct {
	J *X
	K map[string]int
}

func main() {
	raw, _ := hex.DecodeString(data)
	decoder := gob.NewDecoder(bytes.NewReader(raw))

	var x X
	decoder.Decode(&x) // fatal error: runtime: out of memory
	fmt.Println("Decoding finished.")
}
</details>

Smaller Encodings with Struct Tag Options

Struct tags automatically reduce encoded size of structs and improve speed.

We can write less code by using struct tag options:

  • toarray: encode without field names (decode back to original struct)
  • keyasint: encode field names as integers (decode back to original struct)
  • omitempty: omit empty field when encoding
  • omitzero: omit zero-value field when encoding

As a special case, struct field tag "-" omits the field.

NOTE: When a struct uses toarray, the encoder will ignore omitempty and omitzero to prevent position of encoded array elements from changing. This allows decoder to match encoded elements to their Go struct field.

alt text

[!NOTE]
fxamacker/cbor can encode a 3-level nested Go struct to 1 byte!

  • encoding/json: 18 bytes of JSON
  • fxamacker/cbor: 1 byte of CBOR
<details><summary> 🔎&nbsp; Encoding 3-level nested Go struct with omitempty</summary><p/>

https://go.dev/play/p/YxwvfPdFQG2

// Example encoding nested struct (with omitempty tag)
// - encoding/json:  18 byte JSON
// - fxamacker/cbor:  1 byte CBOR

package main

import (
	"encoding/hex"
	"encoding/json"
	"fmt"

	"github.com/fxamacker/cbor/v2"
)

type GrandChild struct {
	Quux int `json:",omitempty"`
}

type Child struct {
	Baz int        `json:",omitempty"`
	Qux GrandChild `json:",omitempty"`
}

type Parent struct {
	Foo Child `json:",omitempty"`
	Bar int   `json:",omitempty"`
}

func cb() {
	results, _ := cbor.Marshal(Parent{})
	fmt.Println("hex(CBOR): " + hex.EncodeToString(results))

	text, _ := cbor.Diagnose(results) // Diagnostic Notation
	fmt.Println("DN: " + text)
}

func js() {
	results, _ := json.Marshal(Parent{})
	fmt.Println("hex(JSON): " + hex.EncodeToString(results))

	text := string(results) // JSON
	fmt.Println("JSON: " + text)
}

func main() {
	cb()
	fmt.Println("-------------")
	js()
}

Output (DN is Diagnostic Notation)

View on GitHub
GitHub Stars1.0k
CategoryDevelopment
Updated4d ago
Forks77

Languages

Go

Security Score

100/100

Audited on Mar 22, 2026

No findings