basecamp/fizzy · error · ActionPack::WebAuthn::InvalidCborError
Invalid simple value: #{info}
Error message
Invalid simple value: #{info} What it means
In decode_float_or_simple, major type 7 with additional-info values 20/21/22/23 (false/true/null/undefined) and 25/26/27 (half/single/double floats) is handled; any other info value (0–19 unassigned simple values, 24 one-byte simple value, 28–31 reserved/break) raises InvalidCborError with the offending value interpolated.
Source
Thrown at lib/action_pack/web_authn/cbor_decoder.rb:194
else
Hash.new.tap do |hash|
read_argument.times do
hash[decode] = decode
end
end
end
end
def decode_float_or_simple
case info = additional_info
when SIMPLE_FALSE_VALUE then false
when SIMPLE_TRUE_VALUE then true
when SIMPLE_NULL_VALUE, SIMPLE_UNDEFINED_VALUE then nil
when TWO_BYTE_VALUE_FOLLOWS then decode_half_float
when FOUR_BYTE_VALUE_FOLLOWS then read_bytes(4).pack("C*").unpack1("g")
when EIGHT_BYTE_VALUE_FOLLOWS then read_bytes(8).pack("C*").unpack1("G")
else
raise ActionPack::WebAuthn::InvalidCborError, "Invalid simple value: #{info}"
end
end
def decode_tag
tag = read_argument
value = decode
case tag
when POSITIVE_BIGNUM_TAG then value.bytes.inject(0) { |n, b| (n << 8) | b }
when NEGATIVE_BIGNUM_TAG then -1 - value.bytes.inject(0) { |n, b| (n << 8) | b }
else value
end
end
def decode_half_float
half = read_bytes(2).pack("C*").unpack1("n")
sign = (half >> 15) & 0x1View on GitHub (pinned to 7aabe74580)
Solutions
- Hex-dump the bytes around the failure offset (the decoder stops exactly at the bad item) and compare against the expected structure.
- Regenerate the payload with a conformant encoder (RFC 8949); never hand-edit CBOR bytes.
- Rescue InvalidCborError and reject the whole payload — one bad item means the byte stream is untrustworthy.
- If decoding untrusted input, wrap the call so malformed data returns 400, not a 500.
Example fix
# before
value = ActionPack::WebAuthn::CborDecoder.decode(bytes) # raises mid-parse on 0xF8
# after — treat any CBOR syntax violation as bad input
begin
value = ActionPack::WebAuthn::CborDecoder.decode(bytes)
rescue ActionPack::WebAuthn::InvalidCborError => e
Rails.logger.info { "Rejected malformed CBOR: #{e.message}" }
return render json: { error: 'malformed payload' }, status: :bad_request
end Defensive patterns
Strategy: try-catch
Try / catch
begin
value = ActionPack::WebAuthn::CborDecoder.decode(bytes)
rescue ActionPack::WebAuthn::InvalidCborError => e
Rails.logger.info { "Rejected CBOR: #{e.message} at producer #{request.remote_ip}" }
render json: { error: 'malformed payload' }, status: :bad_request
end Prevention
- Always encode CBOR with a conformant RFC 8949 library; never hand-edit header bytes.
- Wrap decoder calls so any syntax violation becomes 400, not a 500 stack trace.
- Log the offending message (it interpolates the bad value) to spot fuzzing quickly.
When it happens
Trigger: Decoding bytes like 0xF0 (simple value 16), 0xF8 (one-byte simple value follows), 0xFC/0xFD (reserved 28/29), or a stray 0xFF break code where a value was expected — all shapes that real encoders never emit, so the input is corrupt or hand-crafted.
Common situations: Fuzzed or bit-flipped payloads; test vectors built by incrementing header bytes; random binary data passed as CBOR; buffers shifted by an off-by-one so a type-7 header lands mid-byte.
Related errors
- Reserved additional info: #{info}
- Invalid additional info: #{info}
- Unexpected end of input
- Authenticator data is too short
- Authenticator data is too short for attested credential data
AI-assisted analysis of basecamp/fizzy@7aabe74580 (2026-08-21).
Data as JSON: /api/errors/5ece847e13401ac6.
Report an issue: GitHub.