- Security fixes, reported by Stig Palmquist (CPANSec):
- CVE-2026-110672 decode: free the hash key on "Duplicate keys not
allowed" and on a missing ':' (leak).
- CVE-2026-110673 decode: charge allow_tags "(" nesting against
max_depth (stack overflow).
- CVE-2026-110674 decode: look bare keys up as UTF-8, so the
duplicate check no longer misses or crashes on non-ASCII keys.
- CVE-2026-110675 decode: validate bare hash keys as UTF-8 like
quoted keys (malformed keys).
- CVE-2026-110676 encode: compact allow_bignum Math::BigFloat
values with huge exponents (30MB from 12 bytes).
- CVE-2026-110677 decode: fix the dupkeys_as_arrayref reference
counts (leaked every array).
- CVE-2026-110678 incr_parse: apply max_size to the buffered text
in every context.
- CVE-2026-110680 encode: bound the canonical key snapshot for
growing tied or shared hashes (overflow).
- CVE-2026-110681 new: clone the callbacks and buffer SVs on
ithread clone instead of sharing the parent's pointers.
- CVE-2026-110682 incr_parse: reject a top-level number, true,
false or null unless allow_nonref was set explicitly, as
chunking changes their value. Strings, arrays and objects are
unchanged.
- CVE-2026-110684 encode: release the temporary references when
stringifying overloaded objects (leak).
- CVE-2026-110685 decode_tag: free the tag and its arguments when
THAW dies (leak).
- CVE-2026-110686 decode: keep the filter callbacks alive while
they run (use-after-free when a filter removes itself).
- CVE-2026-110687 canonical: sort byte-string keys as Latin-1.
- CVE-2026-110688 incr_parse: validate UTF-8 only up to the end of
the decoded text (quadratic CPU).
- CVE-2026-110672 decode: free the hash key on "Duplicate keys not
- Add version markers to all module files. (PR #260 demerphq)
- Use utf8n_to_uvchr on Perl 5.32 and later to avoid the deprecated
utf8n_to_uvuni API. (PR #260 demerphq)
- Add schema-based validation for decoded JSON (GH #238):
Cpanel::JSON::XS::Type now provides check_type($data, $schema[,
$found_type]), which validates an already-decoded perl structure
against a type spec built from the existing encoder building
blocks (JSONTYPE* / json_type_arrayof / json_type_hashof /
json_type_anyof), plus the new json_type_optional() for hash keys
that may be absent, and short scalar type name sugar ('Str',
'Int', 'Float', 'Bool', 'Null', 'Any', and nullable 'Str?' etc.)
so a schema reads as "just a hash of keys and types", as
requested. Unlike the encoder's hash type spec, a plain hashref
schema is closed: unknown keys and missing required keys are
reported. New $json->decode_and_validate($json_text, $schema)
method decodes and croaks with all mismatches if validation
fails, using decode()'s own type introspection as ground truth to
avoid perl's usual dual-var/stringified-number ambiguity.
- json_type_optional() and the nullable '?' type-name suffixes
('Str?', 'Int?', 'Float?', 'Bool?') give schemas an explicit way
to declare a key/value as optional instead of demanding a
complete type specification for every key. The encoder now also
understands json_type_optional() directly (it unwraps to the
wrapped type, since encode() only ever sees keys that are
actually present): the exact same type spec built for
check_type()/decode_and_validate() can now be handed to encode()
as-is, instead of croaking with "no type was specified for hash
key '...'" for every optional key. Encoding stays strict by
default otherwise: a hash key with no entry at all in the type
spec still croaks (GH #242).