From 22ae0a731ee478d01c6088c9ad51c3a994f62de2 Mon Sep 17 00:00:00 2001 From: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:14:55 +0530 Subject: [PATCH 1/5] fix: add auth checks to OAuth integration callbacks (#1338) (#7247) Co-authored-by: Cursor --- .../app/api/google-sheet/callback/route.ts | 20 +++++++++++++++---- .../v1/integrations/notion/callback/route.ts | 18 +++++++++++++++-- .../v1/integrations/slack/callback/route.ts | 18 +++++++++++++++-- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/apps/web/app/api/google-sheet/callback/route.ts b/apps/web/app/api/google-sheet/callback/route.ts index 3744ec6be346..676a0a509c3f 100644 --- a/apps/web/app/api/google-sheet/callback/route.ts +++ b/apps/web/app/api/google-sheet/callback/route.ts @@ -1,4 +1,5 @@ import { google } from "googleapis"; +import { getServerSession } from "next-auth"; import { responses } from "@/app/lib/api/response"; import { GOOGLE_SHEETS_CLIENT_ID, @@ -6,18 +7,29 @@ import { GOOGLE_SHEETS_REDIRECT_URL, WEBAPP_URL, } from "@/lib/constants"; +import { hasUserEnvironmentAccess } from "@/lib/environment/auth"; import { createOrUpdateIntegration } from "@/lib/integration/service"; +import { authOptions } from "@/modules/auth/lib/authOptions"; export const GET = async (req: Request) => { - const url = req.url; - const queryParams = new URLSearchParams(url.split("?")[1]); // Split the URL and get the query parameters - const environmentId = queryParams.get("state"); // Get the value of the 'state' parameter - const code = queryParams.get("code"); + const url = new URL(req.url); + const environmentId = url.searchParams.get("state"); + const code = url.searchParams.get("code"); if (!environmentId) { return responses.badRequestResponse("Invalid environmentId"); } + const session = await getServerSession(authOptions); + if (!session) { + return responses.notAuthenticatedResponse(); + } + + const canUserAccessEnvironment = await hasUserEnvironmentAccess(session.user.id, environmentId); + if (!canUserAccessEnvironment) { + return responses.unauthorizedResponse(); + } + if (code && typeof code !== "string") { return responses.badRequestResponse("`code` must be a string"); } diff --git a/apps/web/app/api/v1/integrations/notion/callback/route.ts b/apps/web/app/api/v1/integrations/notion/callback/route.ts index 06e56c77de3b..ea5c69642d63 100644 --- a/apps/web/app/api/v1/integrations/notion/callback/route.ts +++ b/apps/web/app/api/v1/integrations/notion/callback/route.ts @@ -1,7 +1,7 @@ import { NextRequest } from "next/server"; import { TIntegrationNotionConfigData, TIntegrationNotionInput } from "@formbricks/types/integration/notion"; import { responses } from "@/app/lib/api/response"; -import { withV1ApiWrapper } from "@/app/lib/api/with-api-logging"; +import { TSessionAuthentication, withV1ApiWrapper } from "@/app/lib/api/with-api-logging"; import { ENCRYPTION_KEY, NOTION_OAUTH_CLIENT_ID, @@ -10,10 +10,17 @@ import { WEBAPP_URL, } from "@/lib/constants"; import { symmetricEncrypt } from "@/lib/crypto"; +import { hasUserEnvironmentAccess } from "@/lib/environment/auth"; import { createOrUpdateIntegration, getIntegrationByType } from "@/lib/integration/service"; export const GET = withV1ApiWrapper({ - handler: async ({ req }: { req: NextRequest }) => { + handler: async ({ + req, + authentication, + }: { + req: NextRequest; + authentication: NonNullable; + }) => { const url = req.url; const queryParams = new URLSearchParams(url.split("?")[1]); // Split the URL and get the query parameters const environmentId = queryParams.get("state"); // Get the value of the 'state' parameter @@ -26,6 +33,13 @@ export const GET = withV1ApiWrapper({ }; } + const canUserAccessEnvironment = await hasUserEnvironmentAccess(authentication.user.id, environmentId); + if (!canUserAccessEnvironment) { + return { + response: responses.unauthorizedResponse(), + }; + } + if (code && typeof code !== "string") { return { response: responses.badRequestResponse("`code` must be a string"), diff --git a/apps/web/app/api/v1/integrations/slack/callback/route.ts b/apps/web/app/api/v1/integrations/slack/callback/route.ts index d2b58db00206..f254e774d78c 100644 --- a/apps/web/app/api/v1/integrations/slack/callback/route.ts +++ b/apps/web/app/api/v1/integrations/slack/callback/route.ts @@ -5,12 +5,19 @@ import { TIntegrationSlackCredential, } from "@formbricks/types/integration/slack"; import { responses } from "@/app/lib/api/response"; -import { withV1ApiWrapper } from "@/app/lib/api/with-api-logging"; +import { TSessionAuthentication, withV1ApiWrapper } from "@/app/lib/api/with-api-logging"; import { SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, WEBAPP_URL } from "@/lib/constants"; +import { hasUserEnvironmentAccess } from "@/lib/environment/auth"; import { createOrUpdateIntegration, getIntegrationByType } from "@/lib/integration/service"; export const GET = withV1ApiWrapper({ - handler: async ({ req }: { req: NextRequest }) => { + handler: async ({ + req, + authentication, + }: { + req: NextRequest; + authentication: NonNullable; + }) => { const url = req.url; const queryParams = new URLSearchParams(url.split("?")[1]); // Split the URL and get the query parameters const environmentId = queryParams.get("state"); // Get the value of the 'state' parameter @@ -23,6 +30,13 @@ export const GET = withV1ApiWrapper({ }; } + const canUserAccessEnvironment = await hasUserEnvironmentAccess(authentication.user.id, environmentId); + if (!canUserAccessEnvironment) { + return { + response: responses.unauthorizedResponse(), + }; + } + if (code && typeof code !== "string") { return { response: responses.badRequestResponse("`code` must be a string"), From 85a1318f7743b19572e87c9202d00863a3daf23f Mon Sep 17 00:00:00 2001 From: Matti Nannt Date: Fri, 13 Feb 2026 11:06:58 +0100 Subject: [PATCH 2/5] fix: force tar 7.5.7 to resolve Dependabot alerts #249/#264 (#7248) --- package.json | 3 +- pnpm-lock.yaml | 102 +++++++++++++++++++++++++++++++------------------ 2 files changed, 67 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 9fd06683a3bf..0e997ed01e67 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "uuid": "11.1.0", "node-forge": ">=1.3.2", "tar-fs": "2.1.4", + "tar": ">=7.5.7", "typeorm": ">=0.3.26", "systeminformation": "5.27.14", "qs": ">=6.14.1", @@ -97,7 +98,7 @@ "diff": ">=8.0.3" }, "comments": { - "overrides": "Security fixes for transitive dependencies. Remove when upstream packages update: axios (CVE-2025-58754) - awaiting @boxyhq/saml-jackson update | node-forge (Dependabot #230) - awaiting @boxyhq/saml-jackson update | tar-fs (Dependabot #205) - awaiting upstream dependency updates | typeorm (Dependabot #223) - awaiting @boxyhq/saml-jackson update | systeminformation (Dependabot #241) - awaiting @opentelemetry/host-metrics update | qs (Dependabot #245) - awaiting googleapis-common and stripe updates | preact (Dependabot #247) - awaiting next-auth update | fast-xml-parser (Dependabot #270) - awaiting @boxyhq/saml-jackson update | diff (Dependabot #269) - awaiting @microsoft/api-extractor update" + "overrides": "Security fixes for transitive dependencies. Remove when upstream packages update: axios (CVE-2025-58754) - awaiting @boxyhq/saml-jackson update | node-forge (Dependabot #230) - awaiting @boxyhq/saml-jackson update | tar-fs (Dependabot #205) - awaiting upstream dependency updates | tar (Dependabot #249/#264) - awaiting @boxyhq/saml-jackson/sqlite3 dependency updates | typeorm (Dependabot #223) - awaiting @boxyhq/saml-jackson update | systeminformation (Dependabot #241) - awaiting @opentelemetry/host-metrics update | qs (Dependabot #245) - awaiting googleapis-common and stripe updates | preact (Dependabot #247) - awaiting next-auth update | fast-xml-parser (Dependabot #270) - awaiting @boxyhq/saml-jackson update | diff (Dependabot #269) - awaiting @microsoft/api-extractor update" }, "patchedDependencies": { "next-auth@4.24.12": "patches/next-auth@4.24.12.patch" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 71ce808c2dbe..8f337c9df6fd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,6 +9,7 @@ overrides: uuid: 11.1.0 node-forge: '>=1.3.2' tar-fs: 2.1.4 + tar: '>=7.5.7' typeorm: '>=0.3.26' systeminformation: 5.27.14 qs: '>=6.14.1' @@ -27,7 +28,7 @@ importers: dependencies: next: specifier: 16.1.6 - version: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + version: 16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: specifier: 19.2.3 version: 19.2.3 @@ -293,7 +294,7 @@ importers: version: 1.2.6(@types/react-dom@19.2.1(@types/react@19.2.1))(@types/react@19.2.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@sentry/nextjs': specifier: 10.5.0 - version: 10.5.0(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.99.8(esbuild@0.25.12)) + version: 10.5.0(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.99.8(esbuild@0.25.12)) '@t3-oss/env-nextjs': specifier: 0.13.4 version: 0.13.4(arktype@2.1.29)(typescript@5.8.3)(zod@3.24.4) @@ -383,13 +384,13 @@ importers: version: 3.0.1 next: specifier: 16.1.6 - version: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + version: 16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) next-auth: specifier: 4.24.12 - version: 4.24.12(patch_hash=7ac5717a8d7d2049442182b5d83ab492d33fe774ff51ff5ea3884628b77df87b)(next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(nodemailer@7.0.11)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + version: 4.24.12(patch_hash=7ac5717a8d7d2049442182b5d83ab492d33fe774ff51ff5ea3884628b77df87b)(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(nodemailer@7.0.11)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) next-safe-action: specifier: 7.10.8 - version: 7.10.8(next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.24.4) + version: 7.10.8(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.24.4) node-fetch: specifier: 3.3.2 version: 3.3.2 @@ -2661,6 +2662,10 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + '@istanbuljs/schema@0.1.3': resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} @@ -6982,6 +6987,10 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + chromatic@13.3.4: resolution: {integrity: sha512-TR5rvyH0ESXobBB3bV8jc87AEAFQC7/n+Eb4XWhJz6hW3YNxIQPVjcbgLv+a4oKHEl1dUBueWSoIQsOVGTd+RQ==} hasBin: true @@ -9151,10 +9160,6 @@ packages: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} - minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -9163,6 +9168,10 @@ packages: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} engines: {node: '>= 8'} + minizlib@3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} + engines: {node: '>= 18'} + mixpanel@0.18.1: resolution: {integrity: sha512-YD1xfn6WP6ZLQ6Pmgh0KgdXhueJEsrodThMTsHzHMH0VbWa9ck8s+ynDtM83OSgt+yQ61W/SQNrH8Y4wIwocGg==} engines: {node: '>=10.0'} @@ -10872,10 +10881,9 @@ packages: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} - tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + tar@7.5.7: + resolution: {integrity: sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==} + engines: {node: '>=18'} tarn@3.0.2: resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==} @@ -11700,6 +11708,10 @@ packages: yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + yaml@2.8.2: resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} engines: {node: '>= 14.6'} @@ -14104,6 +14116,10 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.2 + '@istanbuljs/schema@0.1.3': {} '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.8.3)(vite@6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.39.1)(tsx@4.19.4)(yaml@2.8.2))': @@ -17033,7 +17049,7 @@ snapshots: '@sentry/core@10.5.0': {} - '@sentry/nextjs@10.5.0(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.99.8(esbuild@0.25.12))': + '@sentry/nextjs@10.5.0(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.99.8(esbuild@0.25.12))': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.38.0 @@ -17046,7 +17062,7 @@ snapshots: '@sentry/vercel-edge': 10.5.0 '@sentry/webpack-plugin': 4.6.1(encoding@0.1.13)(webpack@5.99.8(esbuild@0.25.12)) chalk: 3.0.0 - next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + next: 16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) resolve: 1.22.8 rollup: 4.54.0 stacktrace-parser: 0.1.11 @@ -19538,7 +19554,7 @@ snapshots: promise-inflight: 1.0.1 rimraf: 3.0.2 ssri: 8.0.1 - tar: 6.2.1 + tar: 7.5.7 unique-filename: 1.1.1 transitivePeerDependencies: - bluebird @@ -19613,7 +19629,10 @@ snapshots: chownr@1.1.4: {} - chownr@2.0.0: {} + chownr@2.0.0: + optional: true + + chownr@3.0.0: {} chromatic@13.3.4: {} @@ -20858,6 +20877,7 @@ snapshots: fs-minipass@2.1.0: dependencies: minipass: 3.3.6 + optional: true fs.realpath@1.0.0: {} @@ -22039,8 +22059,7 @@ snapshots: minipass@3.3.6: dependencies: yallist: 4.0.0 - - minipass@5.0.0: {} + optional: true minipass@7.1.2: {} @@ -22048,6 +22067,11 @@ snapshots: dependencies: minipass: 3.3.6 yallist: 4.0.0 + optional: true + + minizlib@3.1.0: + dependencies: + minipass: 7.1.2 mixpanel@0.18.1: dependencies: @@ -22057,7 +22081,8 @@ snapshots: mkdirp-classic@0.5.3: {} - mkdirp@1.0.4: {} + mkdirp@1.0.4: + optional: true mlly@1.8.0: dependencies: @@ -22161,13 +22186,13 @@ snapshots: neo-async@2.6.2: {} - next-auth@4.24.12(patch_hash=7ac5717a8d7d2049442182b5d83ab492d33fe774ff51ff5ea3884628b77df87b)(next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(nodemailer@7.0.11)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + next-auth@4.24.12(patch_hash=7ac5717a8d7d2049442182b5d83ab492d33fe774ff51ff5ea3884628b77df87b)(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(nodemailer@7.0.11)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: '@babel/runtime': 7.28.4 '@panva/hkdf': 1.2.1 cookie: 0.7.2 jose: 4.15.9 - next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + next: 16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) oauth: 0.9.15 openid-client: 5.7.1 preact: 10.28.2 @@ -22178,9 +22203,9 @@ snapshots: optionalDependencies: nodemailer: 7.0.11 - next-safe-action@7.10.8(next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.24.4): + next-safe-action@7.10.8(next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(zod@3.24.4): dependencies: - next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + next: 16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) optionalDependencies: @@ -22194,7 +22219,7 @@ snapshots: postcss: 8.4.31 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - styled-jsx: 5.1.6(react@19.2.3) + styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.3) optionalDependencies: '@next/swc-darwin-arm64': 16.0.10 '@next/swc-darwin-x64': 16.0.10 @@ -22211,7 +22236,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + next@16.1.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(@playwright/test@1.56.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: '@next/env': 16.1.6 '@swc/helpers': 0.5.15 @@ -22220,7 +22245,7 @@ snapshots: postcss: 8.4.31 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - styled-jsx: 5.1.6(react@19.2.3) + styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.2.3) optionalDependencies: '@next/swc-darwin-arm64': 16.1.6 '@next/swc-darwin-x64': 16.1.6 @@ -22271,7 +22296,7 @@ snapshots: npmlog: 6.0.2 rimraf: 3.0.2 semver: 7.7.3 - tar: 6.2.1 + tar: 7.5.7 which: 2.0.2 transitivePeerDependencies: - bluebird @@ -23755,7 +23780,7 @@ snapshots: bindings: 1.5.0 node-addon-api: 7.1.1 prebuild-install: 7.1.3 - tar: 6.2.1 + tar: 7.5.7 optionalDependencies: node-gyp: 8.4.1 transitivePeerDependencies: @@ -23966,10 +23991,12 @@ snapshots: stubborn-utils@1.0.2: {} - styled-jsx@5.1.6(react@19.2.3): + styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.2.3): dependencies: client-only: 0.0.1 react: 19.2.3 + optionalDependencies: + '@babel/core': 7.28.5 stylis@4.3.6: {} @@ -24061,14 +24088,13 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - tar@6.2.1: + tar@7.5.7: dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.1.0 + yallist: 5.0.0 tarn@3.0.2: {} @@ -25016,6 +25042,8 @@ snapshots: yallist@4.0.0: {} + yallist@5.0.0: {} + yaml@2.8.2: {} yargs-parser@18.1.3: From 7495c040489f060bcd9962307029bd2c9d796b11 Mon Sep 17 00:00:00 2001 From: Bhagya Amarasinghe Date: Fri, 13 Feb 2026 16:30:04 +0530 Subject: [PATCH 3/5] fix: update Helm chart path in release workflow from helm-chart/ to charts/formbricks/ (#7250) --- .github/workflows/release-helm-chart.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-helm-chart.yml b/.github/workflows/release-helm-chart.yml index eca5a3d714f8..9464921020ad 100644 --- a/.github/workflows/release-helm-chart.yml +++ b/.github/workflows/release-helm-chart.yml @@ -65,8 +65,8 @@ jobs: set -euo pipefail echo "Updating Chart.yaml with version: ${VERSION}" - yq -i ".version = \"${VERSION}\"" helm-chart/Chart.yaml - yq -i ".appVersion = \"${VERSION}\"" helm-chart/Chart.yaml + yq -i ".version = \"${VERSION}\"" charts/formbricks/Chart.yaml + yq -i ".appVersion = \"${VERSION}\"" charts/formbricks/Chart.yaml echo "✅ Successfully updated Chart.yaml" @@ -77,7 +77,7 @@ jobs: set -euo pipefail echo "Packaging Helm chart version: ${VERSION}" - helm package ./helm-chart + helm package ./charts/formbricks echo "✅ Successfully packaged formbricks-${VERSION}.tgz" From 4538c7bbcb94caf5d8f3d4e9cb0007907207e3cc Mon Sep 17 00:00:00 2001 From: Bhagya Amarasinghe Date: Fri, 13 Feb 2026 18:16:58 +0530 Subject: [PATCH 4/5] fix: remove custom level formatter when using pino multi-transport (#7251) Co-authored-by: Cursor --- packages/logger/src/logger.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/logger/src/logger.ts b/packages/logger/src/logger.ts index 55ba18e41d9e..b8f35396b6bb 100644 --- a/packages/logger/src/logger.ts +++ b/packages/logger/src/logger.ts @@ -35,11 +35,6 @@ const baseLoggerConfig: LoggerOptions = { }, useOnlyCustomLevels: true, timestamp: true, - formatters: { - level: (label) => { - return { level: label }; - }, - }, name: "formbricks", }; @@ -102,9 +97,21 @@ const buildTransport = (): LoggerOptions["transport"] => { return undefined; // Default JSON to stdout }; +const transport = buildTransport(); + +// Pino does not allow custom `formatters` (functions) when using multi-target transports +// because targets run in worker threads and functions cannot be serialized. +// Only attach the level formatter when we're NOT using `{ targets: [...] }`. +const useMultiTransport = transport !== undefined && "targets" in transport; + const loggerConfig: LoggerOptions = { ...baseLoggerConfig, - transport: buildTransport(), + transport, + ...(!useMultiTransport && { + formatters: { + level: (label) => ({ level: label }), + }, + }), }; const pinoLogger: Logger = Pino(loggerConfig); From 08ac490512cdd61c8cd9b3572135c9b5193e9d24 Mon Sep 17 00:00:00 2001 From: Bhagya Amarasinghe Date: Fri, 13 Feb 2026 20:27:08 +0530 Subject: [PATCH 5/5] fix: pino transport target resolution (#7252) Co-authored-by: Cursor Co-authored-by: Matti Nannt --- .github/workflows/sonarqube.yml | 4 ++++ apps/web/Dockerfile | 16 ++++++++++++++++ apps/web/next.config.mjs | 10 ++++++++++ packages/logger/vite.config.ts | 2 +- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml index 4c5ba986f3b3..9f0a1fc2faa4 100644 --- a/.github/workflows/sonarqube.yml +++ b/.github/workflows/sonarqube.yml @@ -9,6 +9,7 @@ on: merge_group: permissions: contents: read + pull-requests: read jobs: sonarqube: name: SonarQube @@ -50,6 +51,9 @@ jobs: pnpm test:coverage - name: SonarQube Scan uses: SonarSource/sonarqube-scan-action@2500896589ef8f7247069a56136f8dc177c27ccf + with: + args: > + -Dsonar.verbose=true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index 0407100d48d1..a54c5040433d 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -126,6 +126,22 @@ RUN chmod -R 755 ./node_modules/@noble/hashes COPY --from=installer /app/node_modules/zod ./node_modules/zod RUN chmod -R 755 ./node_modules/zod +# Pino loads transport code in worker threads via dynamic require(). +# Next.js file tracing only traces static imports, missing runtime-loaded files +# (e.g. pino/lib/transport-stream.js, transport targets). +# Copy the full packages to ensure all runtime files are available. +COPY --from=installer /app/node_modules/pino ./node_modules/pino +RUN chmod -R 755 ./node_modules/pino + +COPY --from=installer /app/node_modules/pino-opentelemetry-transport ./node_modules/pino-opentelemetry-transport +RUN chmod -R 755 ./node_modules/pino-opentelemetry-transport + +COPY --from=installer /app/node_modules/pino-abstract-transport ./node_modules/pino-abstract-transport +RUN chmod -R 755 ./node_modules/pino-abstract-transport + +COPY --from=installer /app/node_modules/otlp-logger ./node_modules/otlp-logger +RUN chmod -R 755 ./node_modules/otlp-logger + # Install prisma CLI globally for database migrations and fix permissions for nextjs user RUN npm install --ignore-scripts -g prisma@6 \ && chown -R nextjs:nextjs /usr/local/lib/node_modules/prisma diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 1d40710a7ee5..ecbc3081ac65 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -35,6 +35,16 @@ const nextConfig = { ], outputFileTracingIncludes: { "/api/auth/**/*": ["../../node_modules/jose/**/*"], + // pino loads transport code in worker threads via dynamic require() — the file tracer + // only traces static imports and misses these runtime-loaded files. + // Include the full pino package (worker.js needs transport-stream.js, etc.) + // and its transport targets with their dependencies. + "/*": [ + "../../node_modules/pino/**/*", + "../../node_modules/pino-opentelemetry-transport/**/*", + "../../node_modules/pino-abstract-transport/**/*", + "../../node_modules/otlp-logger/**/*", + ], }, turbopack: {}, experimental: {}, diff --git a/packages/logger/vite.config.ts b/packages/logger/vite.config.ts index f98ee8538558..b008596de2df 100644 --- a/packages/logger/vite.config.ts +++ b/packages/logger/vite.config.ts @@ -11,7 +11,7 @@ export default defineConfig({ formats: ["es", "cjs"], }, rollupOptions: { - external: ["pino", "pino-pretty", "zod"], + external: ["pino", "pino-pretty", "pino-opentelemetry-transport", "zod"], output: { exports: "named", globals: {