From da290d6cdc9d7dcb686308877c1167fa1d54a827 Mon Sep 17 00:00:00 2001 From: subrata71 Date: Thu, 14 May 2026 14:07:16 +0600 Subject: [PATCH 1/2] fix(security): upgrade postgresql-jdbc to 42.7.11 to remediate CVE-2026-42198 CVE-2026-42198 (CVSS 7.5, HIGH) is a client-side denial-of-service in the PostgreSQL JDBC driver's SCRAM-SHA-256 handshake (affects 42.2.0 through 42.7.10). A malicious or compromised PostgreSQL server can respond with an arbitrarily large PBKDF2 iteration count, causing the client to burn CPU inside PBKDF2 with no effective cap. loginTimeout does not mitigate the issue. In the postgres plugin this is reachable by any authenticated user with datasource-creation rights, who can point a datasource at a hostile server and wedge Appsmith server CPU / Hikari pool. Bump the pinned org.postgresql:postgresql override in postgresPlugin from 42.6.1 to 42.7.11, which introduces scramMaxIterations (default 100,000) to cap iterations before the PBKDF2 computation runs. Refresh the override comment to reflect the current Spring Boot version (3.5.12, which manages 42.7.10) and the new floor for removing the override. Behavior change to coordinate in release notes ---------------------------------------------- pgjdbc 42.7.9 (PR pgjdbc#3866) rewrote PGInterval.getValue() for ~32x throughput and as a side effect now omits zero-valued components from the string representation. The postgres plugin emits this exact string for INTERVAL columns (PostgresPlugin.java, INTERVAL_TYPE_NAME branch: resultSet.getObject(i).toString()). User-visible diff: before: \"1 years 5 mons 0 days 2 hours 0 mins 0.0 secs\" after: \"1 years 5 mons 2 hours\" Apps that regex / equality-check INTERVAL strings (rather than parsing them with a library) will need to adapt. The four PostgresPluginTest assertions that pinned the legacy shape are updated to the new shape. Verification ------------ mvn -pl appsmith-plugins/postgresPlugin test Tests run: 66, Failures: 0, Errors: 0, Skipped: 0 (testcontainers PG) mvn -pl appsmith-plugins/postgresPlugin dependency:tree org.postgresql:postgresql:jar:42.7.11:compile Note: committed with --no-verify because the husky pre-commit hook duplicates staged files at wrong paths under sibling worktrees. Spotless formatting was applied manually before commit via mvn spotless:apply on app/server/appsmith-plugins/postgresPlugin. Will be revisited separately. --- .../appsmith-plugins/postgresPlugin/pom.xml | 6 ++++-- .../com/external/plugins/PostgresPluginTest.java | 16 ++++------------ 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/app/server/appsmith-plugins/postgresPlugin/pom.xml b/app/server/appsmith-plugins/postgresPlugin/pom.xml index 01c00ee5d297..61050f5377eb 100644 --- a/app/server/appsmith-plugins/postgresPlugin/pom.xml +++ b/app/server/appsmith-plugins/postgresPlugin/pom.xml @@ -20,8 +20,10 @@ org.postgresql postgresql - - 42.6.1 + + 42.7.11 diff --git a/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java b/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java index 0010436c5e1c..8e70004adcd4 100644 --- a/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java +++ b/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java @@ -695,9 +695,7 @@ public void testExecute() { assertEquals("2018-11-30T20:45:15Z", node.get("created_on").asText()); assertEquals( "2018-11-30T19:45:15Z", node.get("created_on_tz").asText()); - assertEquals( - "1 years 5 mons 0 days 2 hours 0 mins 0.0 secs", - node.get("interval1").asText()); + assertEquals("1 years 5 mons 2 hours", node.get("interval1").asText()); Assertions.assertThat(node.get("spouse_dob")).isEqualTo(NullNode.getInstance()); // Check the order of the columns. @@ -1070,9 +1068,7 @@ public void testPreparedStatementWithoutQuotes() { assertEquals("2018-11-30T20:45:15Z", node.get("created_on").asText()); assertEquals( "2018-11-30T19:45:15Z", node.get("created_on_tz").asText()); - assertEquals( - "1 years 5 mons 0 days 2 hours 0 mins 0.0 secs", - node.get("interval1").asText()); + assertEquals("1 years 5 mons 2 hours", node.get("interval1").asText()); assertTrue(node.get("spouse_dob").isNull()); assertEquals(1.0, node.get("rating").asDouble(), 0.0); @@ -1149,9 +1145,7 @@ public void testPreparedStatementWithDoubleQuotes() { assertEquals("2018-11-30T20:45:15Z", node.get("created_on").asText()); assertEquals( "2018-11-30T19:45:15Z", node.get("created_on_tz").asText()); - assertEquals( - "1 years 5 mons 0 days 2 hours 0 mins 0.0 secs", - node.get("interval1").asText()); + assertEquals("1 years 5 mons 2 hours", node.get("interval1").asText()); assertTrue(node.get("spouse_dob").isNull()); // Check the order of the columns. @@ -1239,9 +1233,7 @@ public void testPreparedStatementWithSingleQuotes() { assertEquals("2018-11-30T20:45:15Z", node.get("created_on").asText()); assertEquals( "2018-11-30T19:45:15Z", node.get("created_on_tz").asText()); - assertEquals( - "1 years 5 mons 0 days 2 hours 0 mins 0.0 secs", - node.get("interval1").asText()); + assertEquals("1 years 5 mons 2 hours", node.get("interval1").asText()); assertTrue(node.get("spouse_dob").isNull()); // Check the order of the columns. From a9b1412355bfe2485088205e5858ffcddae9e394 Mon Sep 17 00:00:00 2001 From: subrata71 Date: Thu, 14 May 2026 18:27:04 +0600 Subject: [PATCH 2/2] test(postgres): update DateTime_Spec INTERVAL assertions to 42.7.11 compact format CE PR CI surfaced 5 failures in DateTime_Spec.ts after the pgjdbc bump. Same root cause as the unit-test updates: pgjdbc 42.7.9 (PR pgjdbc#3866) changed PGInterval.getValue() to (a) omit zero-valued components and (b) drop the trailing .0 from integer whole seconds. The Cypress assertions hardcoded the legacy 6-field format, so each one needs to be rewritten. Mapping the 7 hardcoded strings: "0 years 11 mons 29 days 23 hours 0 mins 0.0 secs" -> "11 mons 29 days 23 hours" "0 years 1 mons 0 days 0 hours 0 mins 0.0 secs" -> "1 mons" "0 years 0 mons 1 days 0 hours 0 mins 0.0 secs" -> "1 days" "6 years 5 mons 4 days 3 hours 2 mins 1.0 secs" -> "6 years 5 mons 4 days 3 hours 2 mins 1 secs" "0 years 0 mons 3 days 4 hours 5 mins 6.0 secs" -> "3 days 4 hours 5 mins 6 secs" "1 years 3 mons 2 days 6 hours 4 mins 5.0 secs" -> "1 years 3 mons 2 days 6 hours 4 mins 5 secs" "1 years 2 mons 0 days 0 hours 0 mins 0.0 secs" -> "1 years 2 mons" Each expected value matches what CI observed as the actual response. Prettier collapsed the now-shorter assertions to single lines. Committed with --no-verify due to the same husky path-resolution issue under worktrees as the previous commit on this branch. --- .../Postgres_DataTypes/DateTime_Spec.ts | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/DateTime_Spec.ts b/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/DateTime_Spec.ts index 619a7228320f..c6d2b1896b53 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/DateTime_Spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/Postgres_DataTypes/DateTime_Spec.ts @@ -130,19 +130,13 @@ describe( agHelper.RenameQuery("intervalRecords"); dataSources.RunQuery(); dataSources.ReadQueryTableResponse(0).then(($cellData) => { - expect($cellData).to.eq( - "0 years 11 mons 29 days 23 hours 0 mins 0.0 secs", - ); + expect($cellData).to.eq("11 mons 29 days 23 hours"); }); dataSources.ReadQueryTableResponse(1).then(($cellData) => { - expect($cellData).to.eq( - "0 years 1 mons 0 days 0 hours 0 mins 0.0 secs", - ); + expect($cellData).to.eq("1 mons"); }); dataSources.ReadQueryTableResponse(2).then(($cellData) => { - expect($cellData).to.eq( - "0 years 0 mons 1 days 0 hours 0 mins 0.0 secs", - ); + expect($cellData).to.eq("1 days"); }); dataSources.ReadQueryTableResponse(3).then(($cellData) => { expect($cellData).to.eq("21"); @@ -186,9 +180,7 @@ describe( expect($cellData).to.eq("16:05:00"); //time format }); table.ReadTableRowColumnData(0, 6, "v1", 200).then(($cellData) => { - expect($cellData).to.eq( - "6 years 5 mons 4 days 3 hours 2 mins 1.0 secs", - ); //Interval format! + expect($cellData).to.eq("6 years 5 mons 4 days 3 hours 2 mins 1 secs"); //Interval format! }); table.ReadTableRowColumnData(0, 7).then(($cellData) => { expect($cellData).to.eq("19.01.1989"); @@ -228,9 +220,7 @@ describe( expect($cellData).to.eq("04:05:00"); }); table.ReadTableRowColumnData(1, 6, "v1", 200).then(($cellData) => { - expect($cellData).to.eq( - "0 years 0 mons 3 days 4 hours 5 mins 6.0 secs", - ); + expect($cellData).to.eq("3 days 4 hours 5 mins 6 secs"); }); table.ReadTableRowColumnData(1, 7, "v1", 200).then(($cellData) => { expect($cellData).to.eq("29.12.2045"); @@ -270,9 +260,7 @@ describe( expect($cellData).to.eq("04:05:06.789"); }); table.ReadTableRowColumnData(1, 6, "v1", 200).then(($cellData) => { - expect($cellData).to.eq( - "1 years 3 mons 2 days 6 hours 4 mins 5.0 secs", - ); + expect($cellData).to.eq("1 years 3 mons 2 days 6 hours 4 mins 5 secs"); }); table.ReadTableRowColumnData(1, 7, "v1", 200).then(($cellData) => { expect($cellData).to.eq("17.03.2014"); @@ -322,9 +310,7 @@ describe( expect($cellData).to.eq("18:14:16"); }); table.ReadTableRowColumnData(1, 6, "v1", 200).then(($cellData) => { - expect($cellData).to.eq( - "1 years 2 mons 0 days 0 hours 0 mins 0.0 secs", - ); + expect($cellData).to.eq("1 years 2 mons"); }); table.ReadTableRowColumnData(1, 7, "v1", 200).then(($cellData) => { expect($cellData).to.eq("08.01.1999");