Federico Mariani created CAMEL-24170:
----------------------------------------

             Summary: camel dataformats - Umbrella: remaining high/medium 
findings from the July 2026 data format review
                 Key: CAMEL-24170
                 URL: https://issues.apache.org/jira/browse/CAMEL-24170
             Project: Camel
          Issue Type: Task
            Reporter: Federico Mariani
         Attachments: camel-dataformats-review-2026-07-public.md

This umbrella collects the remaining findings from a July 2026 review of the 
Camel *data format* components (JSON: Jackson/JacksonXML + Jackson3 twins, 
Gson, Fastjson, Jsonb, CBOR; XML: JAXB, SOAP; CSV: commons-csv, 
univocity-parsers; fixed/flat: Bindy, Flatpack; YAML: SnakeYAML; binary: Avro, 
Protobuf, Jackson-Avro/Protobuf; archives: zipfile, tarfile; 
compression/encoding: base64, lzf, zip-deflater), plus the DSL model -> reifier 
-> data-format option wiring.

The critical finding and the eight highest-impact highs are filed separately 
with attached failing reproducers: C1=CAMEL-24152, H1=CAMEL-24162, 
H3=CAMEL-24163, H4=CAMEL-24164, H5=CAMEL-24165, H7=CAMEL-24166, H8=CAMEL-24167, 
H12=CAMEL-24168, H14=CAMEL-24169. The full findings document (with all 
file:line references, root-cause traces and the medium/low tail) is attached to 
this issue as {{camel-dataformats-review-2026-07-public.md}}.

A recurring theme: commit {{5dfc5c2857e9}} (CAMEL-22354, "align data formats 
getters/setters to model", released 4.15.0) is the root cause of several 
regressions here (the SnakeYAML critical, the CSV {{format}} regression, the 
YAML {{typeFilter}} builder bug, and the SOAP {{ignoreUnmarshalledHeaders}} 
gaps). A focused audit of everything that commit touched is worthwhile.

h2. Remaining HIGH findings (not filed individually)

* *H2 - camel-jacksonxml {xmlMapper} DSL option requires an undocumented {#} 
prefix.* {JacksonXMLDataFormatReifier} does {properties.put("xmlMapper", 
definition.getXmlMapper())} without {asRef()} (contrast {JsonDataFormatReifier} 
for {objectMapper}). {<jacksonXml xmlMapper="myXmlMapper"/>} fails with 
{NoTypeConversionAvailableException: String -> XmlMapper}; only 
{"#myXmlMapper"} works. Same reifier serves camel-jackson3xml. 
Runtime-reproduced.
* *H9 - camel-univocity-parsers {lazyLoad=true} + {asMap=true} uses a {static 
ThreadLocal} for headers.* {HeaderRowProcessor} stores captured headers in a 
static ThreadLocal; consuming the lazy iterator on another thread (parallel 
split, seda/kafka hand-off) NPEs, and a pooled thread can carry stale headers 
from a different exchange, silently mapping values to wrong keys. 
Runtime-reproduced (cross-thread NPE).
* *H10 - camel-univocity-parsers {lazyLoad=true} leaks the input stream* when 
the iterator is not fully consumed. No on-completion hook (camel-csv fixed the 
identical problem via {addOnCompletion}, CAMEL-15105). Abandoned split / 
partial read / downstream error leaks the reader/FileInputStream.
* *H11 - camel-bindy KVP unmarshal truncates any value containing the key-value 
separator.* {BindyKeyValuePairFactory} does 
{s.split(getKeyValuePairSeparator())} (no limit) and keeps only element [1]; 
{58=a=b} -> {a}. Fix: {split(sep, 2)}. Runtime-reproduced.
* *H13 - camel-bindy fixed-length {UnicodeHelper.indexOf} off-by-one.* Loop 
{index + len < length()} should be {<=}; a delimiter at end-of-record is 
unreachable, then {substring(0, -1)} -> {IndexOutOfBoundsException}. 
Runtime-reproduced.
* *H15 - camel-protobuf JSON unmarshal uses the platform default charset* while 
marshal writes UTF-8 ({new InputStreamReader(inputStream)} vs 
{StandardCharsets.UTF_8}). Asymmetric round-trip on non-UTF-8 JVMs. Fix: pass 
UTF-8.
* *H16 - camel-avro {contentTypeHeader} option silently ignored.* The model 
{AvroDataFormat} declares the attribute (default true) but does not implement 
{ContentTypeHeaderAware}, so the generic reifier never transfers it; {<avro 
contentTypeHeader="false"/>} is dead for the default {avroJackson} library. 
Fix: implement {ContentTypeHeaderAware}.
* *H17 - camel-core YAMLDataFormat.Builder.typeFilter(Class...) joins names 
with "." instead of ",".* {typeFilter(Foo.class, Bar.class)} yields one bogus 
pattern {com.x.Foo.com.y.Bar} matching neither class -> every unmarshal throws. 
Fails closed. Fix: {new StringJoiner(",")}. Runtime-reproduced. (CAMEL-22354.)

h2. MEDIUM findings

_(One additional medium-severity security-hardening item identified in this 
review is intentionally omitted from this public issue and is being handled 
through the private ASF security process per SECURITY.md.)_

* *M2 - Gson unmarshal InputStream fallback ignores {Exchange.CHARSET_NAME}* 
({new InputStreamReader(is)}) while marshal honors it. Same class also in JAXB 
filtered-unmarshal fallback and Jsonb/Fastjson.
* *M3 - Jsonb never sets Content-Type; {contentTypeHeader} is a no-op* (does 
not implement {DataFormatContentTypeHeader}).
* *M4 - Jsonb {Jsonb} instance (AutoCloseable) never closed on stop* (doStop is 
a no-op) - resource leak on restart.
* *M5 - {timezone} silently ignored for avroJackson and protobufJackson* 
(neither reifier Jackson branch transfers it; JSON does).
* *M6 - {avro()} fluent Builder default library is ApacheAvro while the model 
default is Jackson* (CAMEL-20502 leftover) - same logical config resolves 
different implementations per DSL.
* *M7 - Avro/Protobuf schema resolvers use {Class.forName} instead of the Camel 
class resolver* - breaks in Spring Boot fat-jar / Quarkus / OSGi.
* *M8 - camel-avro marshalling a {GenericData.Record} without a configured 
schema throws* instead of using the record's own {GenericContainer} schema.
* *M9 - SOAP fault unmarshalling NPE / UnsupportedOperationException* when the 
fault detail is unknown or a SOAP 1.2 {<Reason>} is missing (peer-controlled 
input; no null-guard, lookup outside try/catch).
* *M10 - JAXB {filterNonXmlChars} corrupts valid supplementary-plane 
characters* (emoji, CJK-ext) - treats surrogate pairs as invalid, replaces with 
two spaces.
* *M11 - CBOR marshal buffers the whole output in memory* ({writeValueAsBytes} 
then copy) instead of {writeValue(stream, graph)}.
* *M12 - univocity fixed-width {recordEndsOnNewline=false} still enables the 
feature* (hardcoded {setRecordEndsOnNewline(true)}).
* *M13 - camel-csv {captureHeaderRecord=true} ignored with {lazyLoad=true}*, 
and the header row is consumed and lost (only the bulk unmarshaller sets the 
header).
* *M14 - camel-bindy CSV blank lines manufacture phantom empty records* (or 
fail if a field is required), unlike KVP which skips blank lines. 
Runtime-reproduced.
* *M15 - camel-bindy CSV {defaultValue} not applied when exactly one trailing 
field is missing* (off-by-one {pos < totalFields}); {setDefaultValuesForFields} 
also NPEs on gapped positions. Runtime-reproduced.
* *M16 - camel-bindy CSV marshal of a null {@OneToMany} list drops the child 
columns* (dead code passes {Field.class} as the element type). 
Runtime-reproduced.
* *M17 - camel-bindy {@CsvRecord(allowEmptyStream=true)} discards real data 
when {InputStream.available()==0}* (a legal return for non-empty streams); two 
different {allowEmptyStream} flags. Runtime-reproduced.
* *M18 - camel-flatpack marshal drops the first data row with the default 
{ignoreFirstRecord=true}* ({printHeader()} already emits headers; 
unmarshal->marshal round trip loses record #1).

h2. LOW findings
See the attached document for the low-severity tail (base64 urlSafe CRLF 
chunking and decode-side {lineSeparator} validation; Flatpack 
{getDataFormatName()} typo {"flatback"}; Bindy {DefaultFactoryRegistry} HashMap 
hot-path race and other Bindy quoting/offset/locale nits; camel-csv bulk reader 
leak on parser-construct failure; {useOrderedMaps}+{ignoreHeaderCase} ordering; 
fixed-width reifier {Integer.parseInt("null")}; jackson {useList} clobbering 
{collectionType}; jackson3 type-converter module-loss and dropped 
{canSerialize} guard; jackson {enableJacksonTypeConverter} dead property; 
non-mandatory {unmarshalTypeName} resolution; tarfile-vs-zipfile twin drift - 
empty-tar throw, {hasNext()} non-idempotence dropping zero-byte entries, 
marshal NPE on {CamelFileName="/"}; Avro resolver unconditional 
{URLDecoder.decode} and dead {validate} option; JAXB WARN-level payload 
logging; SnakeYAML lifecycle/type-filter widening; zip-deflater 
compressionLevel late validation).

h2. Verified NON-issues (no action)
JAXB XXE (all unmarshal paths use the hardened {StaxConverter}); fastjson2 
autotype off by default; jackson3 missing {BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES} 
(constant removed upstream); zip-slip ({jailStartingDirectory=true}); SnakeYAML 
default {SafeConstructor} posture and billion-laughs limits.

----
_Reported by Claude Code on behalf of Federico Mariani (Croway). Full findings 
document attached._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to