basecamp/fizzy · error · ActionPack::WebAuthn::InvalidCborError
Invalid additional info: #{info}
Error message
Invalid additional info: #{info} What it means
read_argument's else-branch fires for additional-info 31 — the indefinite-length/break marker — used where a definite argument is required (for example a positive-integer header 0x1F, or an argument byte of 0xFF leaking into an integer/text context). RFC 8949 allows info 31 only for streaming strings/arrays/maps, so anywhere else it is a protocol violation and InvalidCborError is raised.
Source
Thrown at lib/action_pack/web_authn/cbor_decoder.rb:237
mantissa == 0 ? Float::INFINITY : Float::NAN
else
Math.ldexp(mantissa + 1024, exponent - 25)
end
sign == 1 ? -value : value
end
def read_argument
case info = additional_info
when SIMPLE_VALUE_RANGE then info
when SINGLE_BYTE_VALUE_FOLLOWS then read_byte
when TWO_BYTE_VALUE_FOLLOWS then read_bytes(2).pack("C*").unpack1("n")
when FOUR_BYTE_VALUE_FOLLOWS then read_bytes(4).pack("C*").unpack1("N")
when EIGHT_BYTE_VALUE_FOLLOWS then read_bytes(8).pack("C*").unpack1("Q>")
when RESERVED_VALUE_RANGE
raise ActionPack::WebAuthn::InvalidCborError, "Reserved additional info: #{info}"
else
raise ActionPack::WebAuthn::InvalidCborError, "Invalid additional info: #{info}"
end
end
def additional_info(consume: true)
byte = consume ? read_byte : peek
byte & 0b00011111
end
def indefinite_length?
read_byte if additional_info(consume: false) == INDEFINITE_LENGTH_MAJOR_TYPE
end
def break_code?
read_byte if peek == BREAK_CODE
end
def read_bytes(length)
raise ActionPack::WebAuthn::InvalidCborError, "Unexpected end of input" if @position + length > @bytes.lengthView on GitHub (pinned to 7aabe74580)
Solutions
- Hex-dump around the failure offset: a header ending in 0x1F or a stray 0xFF in length position confirms misalignment.
- Emit the payload from a conformant encoder; do not concatenate partial items.
- Validate the byte layout in tests against a golden vector from RFC 8949's appendix.
- Rescue InvalidCborError centrally and reject the payload — misaligned CBOR cannot be recovered.
Example fix
# before
combined = indefinite_chunk + definite_chunk # misaligned concatenation
ActionPack::WebAuthn::CborDecoder.decode(combined)
# after — decode each item as its own complete CBOR sequence item
[chunk_a, chunk_b].each { |c| ActionPack::WebAuthn::CborDecoder.decode(c) } Defensive patterns
Strategy: try-catch
Try / catch
begin
value = ActionPack::WebAuthn::CborDecoder.decode(bytes)
rescue ActionPack::WebAuthn::InvalidCborError => e
render json: { error: 'malformed CBOR payload' }, status: :bad_request
end Prevention
- Close every indefinite-length item with 0xFF and never mix partial indefinite streams with definite items.
- Round-trip test custom encoders against the decoder.
- Hex-dump failures: header low-bits of 0x1F or stray 0xFF in length position mean misalignment.
When it happens
Trigger: Bytes like 0x1F, 0x3F, 0x5F (typed headers with break-info), or a 0xFF break code appearing where the parser expects a length argument — typical when a definite/indefinite concatenation is mixed up or the buffer is misaligned by one byte.
Common situations: Merging a hand-written indefinite-length item with definite-length items; off-by-one slicing that shifts headers; fuzzed payloads; decoders fed the CBOR sequence's second item mid-item of the first.
Related errors
- Invalid simple value: #{info}
- Reserved additional info: #{info}
- Input exceeds maximum size
- Unexpected end of input
- Maximum nesting depth exceeded
AI-assisted analysis of basecamp/fizzy@7aabe74580 (2026-08-21).
Data as JSON: /api/errors/2fbe2c467de00c3d.
Report an issue: GitHub.