Skip to content

Commit eeebff8

Browse files
authored
Merge pull request #2846 from hongwei1/develop
fix(deps): upgrade avro4s 1.8.2→4.1.2 to patch CVE-2024-47561 (CVSS 9.8); remove stale deps
2 parents aad6300 + ea098f4 commit eeebff8

11 files changed

Lines changed: 149 additions & 184 deletions

File tree

obp-api/pom.xml

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,6 @@
2020
<artifactId>obp-commons</artifactId>
2121
</dependency>
2222

23-
<dependency>
24-
<groupId>com.github.everit-org.json-schema</groupId>
25-
<artifactId>org.everit.json.schema</artifactId>
26-
<version>1.6.1</version>
27-
</dependency>
2823
<!-- Upgraded from 1.4.14 (EOL branch) to 1.5.18. 1.4.x is end-of-life as of
2924
2024; 1.5.x is the supported branch and requires Java 11+ (which we target).
3025
Fixes CVE-2024-12798 (RCE via JaninoEventEvaluator in 1.4.x). -->
@@ -41,6 +36,7 @@
4136
<groupId>net.databinder.dispatch</groupId>
4237
<artifactId>dispatch-core_${scala.version}</artifactId>
4338
<version>0.13.1</version>
39+
<scope>test</scope>
4440
</dependency>
4541
<dependency>
4642
<groupId>org.json4s</groupId>
@@ -121,21 +117,20 @@
121117
<artifactId>protobuf-java</artifactId>
122118
<version>3.25.5</version>
123119
</dependency>
124-
<!-- Pin snappy-java to override the 1.1.1.3 pulled in transitively by avro 1.8.2.
120+
<!-- Pin org.apache.avro:avro to 1.11.4 to override the 1.9.2 pulled in transitively
121+
by avro4s 4.1.2. Fixes CVE-2024-47561 (CVSS 9.8 — RCE via schema parsing). -->
122+
<dependency>
123+
<groupId>org.apache.avro</groupId>
124+
<artifactId>avro</artifactId>
125+
<version>${apache.avro.version}</version>
126+
</dependency>
127+
<!-- Pin snappy-java to override older versions pulled in transitively by avro.
125128
Fixes CVE-2023-34453, CVE-2023-34454, CVE-2023-34455, CVE-2023-43642. -->
126129
<dependency>
127130
<groupId>org.xerial.snappy</groupId>
128131
<artifactId>snappy-java</artifactId>
129132
<version>1.1.10.4</version>
130133
</dependency>
131-
<!-- Pin commons-beanutils to override the 1.9.2 pulled in transitively via
132-
everit json-schema → commons-validator. Fixes CVE-2025-48734, CVE-2019-10086;
133-
1.11.0 adds the Improper-Access-Control fix (GHSA on top of those). -->
134-
<dependency>
135-
<groupId>commons-beanutils</groupId>
136-
<artifactId>commons-beanutils</artifactId>
137-
<version>1.11.0</version>
138-
</dependency>
139134
<!-- Pin msal4j to override the older version pulled in transitively by
140135
mssql-jdbc → azure-identity. Fixes CVE-2024-35255 (elevation of
141136
privilege, fixed upstream in 1.15.1). Not used directly in source —
@@ -177,11 +172,6 @@
177172
<artifactId>cglib</artifactId>
178173
<version>3.3.0</version>
179174
</dependency>
180-
<dependency>
181-
<groupId>org.apache.httpcomponents</groupId>
182-
<artifactId>httpclient</artifactId>
183-
<version>4.5.14</version>
184-
</dependency>
185175
<dependency>
186176
<groupId>org.apache.commons</groupId>
187177
<artifactId>commons-pool2</artifactId>
@@ -241,7 +231,7 @@
241231
<dependency>
242232
<groupId>com.sksamuel.avro4s</groupId>
243233
<artifactId>avro4s-core_${scala.version}</artifactId>
244-
<version>${avro.version}</version>
234+
<version>${avro4s.version}</version>
245235
</dependency>
246236
<dependency>
247237
<groupId>org.apache.commons</groupId>
@@ -312,19 +302,14 @@
312302
<artifactId>json-smart</artifactId>
313303
</dependency>
314304
<!-- ********** flexmark START ********** -->
315-
<!-- Library flexmark-all v0.40.8 is replaced with used modules -->
305+
<!-- Library flexmark-all v0.40.8 is replaced with used module -->
316306
<!-- https://mvnrepository.com/artifact/com.vladsch.flexmark/flexmark-profile-pegdown -->
317307
<dependency>
318308
<groupId>com.vladsch.flexmark</groupId>
319309
<artifactId>flexmark-profile-pegdown</artifactId>
320310
<version>0.40.8</version>
321311
</dependency>
322-
<!-- https://mvnrepository.com/artifact/com.vladsch.flexmark/flexmark-util-options -->
323-
<dependency>
324-
<groupId>com.vladsch.flexmark</groupId>
325-
<artifactId>flexmark-util-options</artifactId>
326-
<version>0.64.0</version>
327-
</dependency>
312+
328313
<!-- https://mvnrepository.com/artifact/org.web3j/core -->
329314
<dependency>
330315
<groupId>org.web3j</groupId>
@@ -422,6 +407,7 @@
422407
<groupId>org.asynchttpclient</groupId>
423408
<artifactId>async-http-client</artifactId>
424409
<version>2.15.0</version>
410+
<scope>test</scope>
425411
<exclusions>
426412
<exclusion>
427413
<artifactId>javax.activation</artifactId>
@@ -514,11 +500,12 @@
514500
<artifactId>jackson-databind</artifactId>
515501
<!-- version managed by jackson-bom in parent pom -->
516502
</dependency>
517-
<!-- https://mvnrepository.com/artifact/tools.jackson.dataformat/jackson-dataformat-yaml -->
503+
<!-- com.fasterxml YAML module (Jackson 2.x), version managed by jackson-bom in parent pom.
504+
Replaces the incompatible tools.jackson 3.x line so a single Jackson generation is on
505+
the classpath. YAMLUtils uses com.fasterxml.jackson.dataformat.yaml.YAMLFactory. -->
518506
<dependency>
519-
<groupId>tools.jackson.dataformat</groupId>
507+
<groupId>com.fasterxml.jackson.dataformat</groupId>
520508
<artifactId>jackson-dataformat-yaml</artifactId>
521-
<version>3.0.4</version>
522509
</dependency>
523510
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
524511
<dependency>

obp-api/src/main/scala/code/api/dynamic/endpoint/OBPAPIDynamicEndpoint.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,9 @@ package code.api.dynamic.endpoint
2828

2929
import APIMethodsDynamicEndpoint.ImplementationsDynamicEndpoint
3030
import code.api.OBPRestHelper
31-
import code.api.dynamic.endpoint.helper.DynamicEndpoints
32-
import code.api.util.{APIUtil, VersionedOBPApis}
31+
import code.api.util.VersionedOBPApis
3332
import code.util.Helper.MdcLoggable
3433
import com.openbankproject.commons.util.{ApiVersion,ApiVersionStatus}
35-
import net.liftweb.common.{Box, Full}
36-
import org.apache.http.HttpStatus
3734

3835
/*
3936
This file defines which endpoints from all the versions are available in v4.0.0

obp-api/src/main/scala/code/api/dynamic/entity/projection/ProjectionDualWrite.scala

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ import org.json4s.JsonAST.JObject
99
/**
1010
* Keeps a record's projection row in sync on the write path (DE_indexing, Phase 3). Guarded by
1111
* `projectionEnabled` and a no-op unless the entity has a `ready` projection — so it changes nothing
12-
* by default. Uses `DoobieUtil.runQuery`, which reuses Lift's request connection, so the projection
13-
* upsert/delete participates in the SAME transaction as the canonical blob write (commit/rollback
14-
* together). Scalar fields only (spatial dual-write is Phase 4).
12+
* by default. Uses `DoobieUtil.runUpdate` so the INSERT is committed even when called outside an
13+
* explicit request-scope transaction (e.g. dynamic-entity POST handlers that don't wrap in
14+
* `withBusinessDBTransaction`). When a request-scope proxy IS present, `runUpdate` still reuses it
15+
* via `transactorFromConnection`. Scalar fields only (spatial dual-write is Phase 4).
1516
*/
1617
object ProjectionDualWrite extends MdcLoggable {
1718

18-
/** Upsert the record's ready indexed scalar columns into the projection (called after the blob save). */
1919
def onSave(bankId: Option[String], entityName: String, dataId: String, body: JObject): Unit =
2020
withReadyScalarFields(bankId, entityName) { (safeTable, fields) =>
2121
val cols = fields.map { case (f, spec) =>
@@ -24,13 +24,12 @@ object ProjectionDualWrite extends MdcLoggable {
2424
ProjectionDDL.sqlColumnType(spec.fieldType.toString),
2525
ProjectionCoerce.toColumnValue(body \ f, spec.fieldType))
2626
}
27-
DoobieUtil.runQuery(ProjectionStore.upsert(safeTable, dataId, cols))
27+
DoobieUtil.runUpdate(ProjectionStore.upsert(safeTable, dataId, cols))
2828
}
2929

30-
/** Delete the record's projection row (called after the blob delete; FK cascade is a backstop). */
3130
def onDelete(bankId: Option[String], entityName: String, dataId: String): Unit =
3231
withReadyScalarFields(bankId, entityName) { (safeTable, _) =>
33-
DoobieUtil.runQuery(ProjectionStore.delete(safeTable, dataId))
32+
DoobieUtil.runUpdate(ProjectionStore.delete(safeTable, dataId))
3433
}
3534

3635
private def withReadyScalarFields(bankId: Option[String], entityName: String)

obp-api/src/main/scala/code/api/util/APIUtil.scala

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,34 +1416,12 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
14161416
//ended -- Filtering and Paging relevant methods ////////////////////////////
14171417

14181418

1419-
/** Import this object's methods to add signing operators to dispatch.Request */
14201419
object OAuth {
1421-
import dispatch.{Req => Request}
1422-
1423-
import scala.collection.Map
1424-
14251420
case class Consumer(key: String, secret: String)
14261421
case class Token(value: String, secret: String)
14271422

14281423
/** Out-of-band callback code */
14291424
val oob = "oob"
1430-
1431-
/** Add OAuth operators to dispatch.Request */
1432-
implicit def Request2RequestSigner(r: Request) = new RequestSigner(r)
1433-
1434-
class RequestSigner(rb: Request) {
1435-
/** sign a request with a consumer and a token, e.g. an OAuth-signed API request */
1436-
def <@ (consumer: Consumer, token: Token): Request = {
1437-
rb <:< Map("Authorization" -> s"""DirectLogin token="${token.value}"""")
1438-
}
1439-
def <@ (consumerAndToken: Option[(Consumer,Token)]): Request = {
1440-
consumerAndToken match {
1441-
case Some((_, token)) =>
1442-
rb <:< Map("Authorization" -> s"""DirectLogin token="${token.value}"""")
1443-
case None => rb
1444-
}
1445-
}
1446-
}
14471425
}
14481426

14491427
/*

obp-api/src/main/scala/code/api/util/JwtUtil.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import com.nimbusds.jose.util.{DefaultResourceRetriever, JSONObjectUtils}
1515
import com.nimbusds.jwt.proc.{BadJWTException, DefaultJWTProcessor}
1616
import com.nimbusds.jwt.{JWTClaimsSet, SignedJWT}
1717
import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet
18-
import dispatch.Future
1918
import net.liftweb.common.{Box, Empty, Failure, Full}
2019

2120
object JwtUtil extends MdcLoggable {

obp-api/src/main/scala/code/bankconnectors/AvroSerializer.scala

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,34 @@ import java.io.{ByteArrayOutputStream, InputStream}
55
import com.sksamuel.avro4s._
66

77
import scala.concurrent.{ExecutionContext, Future}
8-
import scala.util.Try
8+
import scala.util.Success
99

10-
/**
11-
* Provides generic serialization/deserialization
12-
*/
1310
trait AvroSerializer {
1411

15-
def serialize[T: SchemaFor : ToRecord](event: T)(implicit executionContext: ExecutionContext): String = {
12+
def serialize[T: Encoder](event: T)(implicit executionContext: ExecutionContext): String = {
1613
val baos = new ByteArrayOutputStream()
17-
val output = AvroOutputStream.json[T](baos)
14+
val output = AvroOutputStream.json[T].to(baos).build()
1815
output.write(event)
1916
output.close()
20-
val r = baos.toString("UTF-8")
21-
r
17+
baos.toString("UTF-8")
2218
}
2319

24-
def serializeFuture[T: SchemaFor : ToRecord](event: T)(implicit executionContext: ExecutionContext): Future[String] =
20+
def serializeFuture[T: Encoder](event: T)(implicit executionContext: ExecutionContext): Future[String] =
2521
Future(serialize(event))
2622

27-
def deserializeFuture[T >: Null : SchemaFor : FromRecord](data: String)(implicit executionContext: ExecutionContext): Future[Option[T]] =
23+
def deserializeFuture[T >: Null : Decoder](data: String)(implicit executionContext: ExecutionContext): Future[Option[T]] =
2824
Future(deserialize[T](data))
2925

30-
def deserialize[T >: Null : SchemaFor : FromRecord](data: String)(implicit executionContext: ExecutionContext): Option[T] = {
31-
32-
val input = AvroInputStream.json[T](new StringInputStream(data))
33-
val result: Try[T] = input.singleEntity
34-
result.toOption
26+
def deserialize[T >: Null : Decoder](data: String)(implicit executionContext: ExecutionContext): Option[T] = {
27+
val schema = implicitly[Decoder[T]].schema
28+
val input = AvroInputStream.json[T].from(new StringInputStream(data)).build(schema)
29+
val result = input.tryIterator.collectFirst { case Success(v) => v }
30+
input.close()
31+
result
3532
}
3633

3734
class StringInputStream(s: String) extends InputStream {
38-
private val bytes = s.getBytes
35+
private val bytes = s.getBytes("UTF-8")
3936

4037
private var pos = 0
4138

@@ -44,7 +41,7 @@ trait AvroSerializer {
4441
} else {
4542
val r = bytes(pos)
4643
pos += 1
47-
r.toInt
44+
r.toInt & 0xFF
4845
}
4946
}
50-
}
47+
}

obp-api/src/main/scala/code/bankconnectors/akka/AkkaConnector_vDec2018.scala

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import com.openbankproject.commons.dto._
1818
import com.openbankproject.commons.model._
1919
import com.openbankproject.commons.model.enums.StrongCustomerAuthenticationStatus.SCAStatus
2020
import com.openbankproject.commons.model.enums.{AccountAttributeType, CardAttributeType, ChallengeType, CustomerAttributeType, ProductAttributeType, StrongCustomerAuthentication, TransactionAttributeType, TransactionRequestStatus}
21-
import com.sksamuel.avro4s.SchemaFor
2221
import net.liftweb.common.{Box, Full}
2322
import com.openbankproject.commons.util.JsonAliases.parse
2423

@@ -55,8 +54,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
5554
inboundStatus,
5655
inboundAdapterInfoInternal)
5756
),
58-
outboundAvroSchema = Some(parse(SchemaFor[OutBoundGetAdapterInfo]().toString(true))),
59-
inboundAvroSchema = Some(parse(SchemaFor[InBoundGetAdapterInfo]().toString(true))),
57+
outboundAvroSchema = None,
58+
inboundAvroSchema = None,
6059
adapterImplementation = Some(AdapterImplementation("- Core", 1))
6160
)
6261
override def getAdapterInfo(callContext: Option[CallContext]): Future[Box[(InboundAdapterInfoInternal, Option[CallContext])]] = {
@@ -81,8 +80,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
8180
List(bankCommons)
8281
)
8382
),
84-
outboundAvroSchema = Some(parse(SchemaFor[OutBoundGetBanks]().toString(true))),
85-
inboundAvroSchema = Some(parse(SchemaFor[InBoundGetBanks]().toString(true))),
83+
outboundAvroSchema = None,
84+
inboundAvroSchema = None,
8685
adapterImplementation = Some(AdapterImplementation("- Core", 2))
8786
)
8887

@@ -110,8 +109,8 @@ object AkkaConnector_vDec2018 extends Connector with AkkaConnectorActorInit {
110109
bankCommons
111110
)
112111
),
113-
outboundAvroSchema = Some(parse(SchemaFor[OutBoundGetBank]().toString(true))),
114-
inboundAvroSchema = Some(parse(SchemaFor[InBoundGetBank]().toString(true))),
112+
outboundAvroSchema = None,
113+
inboundAvroSchema = None,
115114
adapterImplementation = Some(AdapterImplementation("- Core", 5))
116115
)
117116
override def getBank(bankId : BankId, callContext: Option[CallContext]): Future[Box[(Bank, Option[CallContext])]] = {

0 commit comments

Comments
 (0)