[ 
https://issues.apache.org/jira/browse/CAMEL-24132?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18096830#comment-18096830
 ] 

Claus Ibsen commented on CAMEL-24132:
-------------------------------------

Fixed via https://github.com/apache/camel/pull/24794

> camel-jpa: medium-severity findings from July 2026 component review (umbrella)
> ------------------------------------------------------------------------------
>
>                 Key: CAMEL-24132
>                 URL: https://issues.apache.org/jira/browse/CAMEL-24132
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-jpa
>            Reporter: Federico Mariani
>            Assignee: Claus Ibsen
>            Priority: Minor
>             Fix For: 4.22.0
>
>
> h3. Overview
> This is an umbrella issue tracking 7 medium-severity findings from a broader 
> code review of {{camel-jpa}} (July 2026), grouped here rather than filed 
> individually since none is independently critical. High-severity findings 
> from the same review were filed separately as standalone issues.
> h3. M1 -- JpaPollingConsumer.receiveNoWait() can block indefinitely
> JpaPollingConsumer.java:186-189 implements {{receiveNoWait()}} by simply 
> delegating to {{receive()}}, which runs a full transaction and acquires a 
> {{PESSIMISTIC_WRITE}} lock by default -- it can block on row locks for an 
> unbounded time. This violates the {{PollingConsumer}} contract that 
> {{receiveNoWait()}} returns immediately. At minimum it should apply a NOWAIT 
> lock hint (or no lock) rather than reusing {{receive()}} as-is.
> h3. M2 -- receive(timeout) never cancels the background task on timeout
> JpaPollingConsumer.java:192-212: on {{TimeoutException}}, the method returns 
> {{null}} but never calls {{future.cancel(true)}}. The submitted task keeps 
> running in the background -- holding/awaiting DB locks -- and, once it 
> eventually completes, leaks its {{EntityManager}} (see the related EM-leak 
> issue) and its {{Exchange}}. Under repeated timeouts (e.g. {{pollEnrich}} 
> against a locked table with a short timeout), abandoned tasks accumulate in 
> the shared, bounded thread pool, and later polls start timing out purely from 
> queueing.
> h3. M3 -- JpaPollingConsumer + nativeQuery + default consumeLockEntity always 
> fails
> JpaPollingConsumer.java:143-145 calls {{innerQuery.setLockMode(...)}} 
> whenever {{consumeLockEntity}} is {{true}} (the default). Per the JPA spec, 
> {{Query.setLockMode}} throws {{IllegalStateException}} for anything other 
> than a JPQL SELECT / CriteriaQuery -- i.e. for every native query (and for 
> update-style named queries). {{pollEnrich("jpa:X?nativeQuery=...")}} can 
> never succeed without the caller explicitly setting 
> {{consumeLockEntity=false}}. The call should be guarded (skipped for native 
> queries), or the requirement should be documented prominently.
> h3. M4 -- JpaMessageIdRepository.add() turns a concurrent-insert race into a 
> failed exchange instead of a duplicate signal
> JpaMessageIdRepository.java:102-111 is check-then-insert. 
> {{MessageProcessed}} has a unique constraint on {{(processorName, 
> messageId)}}, so when two exchanges race on the same id (parallel threads or 
> a clustered deployment sharing the table), the loser hits a constraint 
> violation at {{flush()}}, which the {{catch}} block wraps and rethrows as a 
> {{PersistenceException}} -- *failing the exchange* -- instead of treating it 
> as "duplicate detected" and returning {{false}}. For a repository whose 
> entire purpose is cluster-safe idempotency, the constraint-violation race 
> should be caught and mapped to {{return false}}.
> h3. M5 -- the CAMEL-22534 parallel-EntityManager fix only covers the Splitter
> CAMEL-22534 made the Splitter strip the {{CamelEntityManager}} exchange 
> property from parallel sub-exchange copies. 
> {{multicast(parallelProcessing)}}, {{recipientList(parallel)}} and 
> {{wireTap}} still copy exchange properties by default, so parallel branches 
> through those EIPs can share the same non-thread-safe {{HashMap<String, 
> EntityManager>}} ({{JpaHelper.getEntityManagerMap}}) *and* the same 
> {{EntityManager}} instances across threads -- both concurrent EM use and map 
> corruption are possible. Consider moving the property-strip into a shared 
> place (e.g. {{MulticastProcessor}}), or making the JPA helper's map 
> thread-safe / per-thread.
> h3. M6 -- JpaProducer.isUseExecuteUpdate() misclassifies legitimate SELECTs
> JpaProducer.java:145-164 decides between {{executeUpdate()}} and 
> {{getResultList()}} by testing whether the raw query string starts with 
> {{"select"}} (case-insensitive, offset 0, no trimming). A query with leading 
> whitespace/newline, a native CTE ({{WITH x AS (...) SELECT ...}}), or a 
> parenthesized select is misclassified as an update and routed to 
> {{executeUpdate()}}, which the JPA provider rejects. The string should be 
> trimmed first, and {{WITH}} should also be recognized as a select-style query 
> (or, more robustly, only auto-detect the update keywords 
> {{insert|update|delete}} and default to select otherwise).
> h3. Note
> A 7th medium finding from the same review (header-supplied query parameters 
> being auto-evaluated as a Simple expression) is *not* included here: it falls 
> under the project's documented in-scope security vulnerability classes 
> (expression injection where the framework itself evaluates untrusted input) 
> and is being routed through the private SECURITY.md disclosure process 
> instead of a public issue.
> See also the four related high-severity issues filed from the same review.
> _Claude Code on behalf of Croway_



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

Reply via email to