Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.
Open advisories
23 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.
Budibase automation steps (outgoing webhook, Zapier, n8n, Slack, Discord, Make.com) make server-side HTTP requests to user-provided URLs using node-fetch directly, completely bypassing the IP blacklist protection that exists in the REST API integration. Additionally, the REST API blacklist itself defaults to empty when BLACKLISTIPS is not configured. Vulnerable Code Automation Steps (No Blacklist) All automation steps use fetch() directly without any IP validation: packages/server/src/automations/steps/outgoingWebhook.ts line 69: packages/server/src/automations/steps/zapier.ts line 34: packages/server/src/automations/steps/n8n.ts line 53: packages/server/src/automations/steps/slack.ts line 20: packages/server/src/automations/steps/discord.ts line 29: REST API Integration (Empty Default Blacklist) packages/server/src/integrations/rest.ts line 684: But BLACKLISTIPS env var defaults to undefined, so the blacklist is empty: packages/backend-core/src/blacklist/blacklist.ts lines…
Recommended action: Upgrade to 3.41.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The /api/users/metadata and /api/users/metadata/:id endpoints in @budibase/server return full global user profiles to any user with POWER role or above. For SSO-authenticated users (OIDC, Google), the response includes oauth2.accessToken and oauth2.refreshToken fields, leaking identity provider credentials to other users who should not have access to them. Details When a user authenticates via SSO (OIDC or Google), the OAuth2 tokens are stored in the global CouchDB user document at packages/backend-core/src/auth/auth.ts:170-173: The user metadata endpoints are protected by PermissionType.USER, PermissionLevel.READ (packages/server/src/api/routes/user.ts:11), which maps to the POWER permission set (packages/backend-core/src/security/permissions.ts:99). Path 1 — List all users (GET /api/users/metadata): 1. controller.fetchMetadata → sdk.users.fetchMetadata() (packages/server/src/sdk/users/utils.ts:78) 2. → getGlobalUsers() → getRawGlobalUsers()…
Recommended action: Upgrade to 3.39.25 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
enrichContext at packages/server/src/sdk/workspace/queries/queries.ts:121-138 substitutes parameter values into the raw JSON body of a query, then JSON.parses the result. The validator validateQueryInputs at packages/server/src/api/controllers/query/index.ts:61-71 rejects only Handlebars markers ({{, }}) in user input and does not escape JSON metacharacters (", \, }). A parameter value containing a closing quote and additional keys lifts attacker-controlled fields into the parsed filter object. For Mongo find, the parsed filter passes directly to collection.find() (packages/server/src/integrations/mongodb.ts:506-510). Duplicate-key JSON parsing overrides the builder's {name: "..."} with {name: {$exists: true}} and returns every document. The same primitive against an updateMany query (mongodb.ts:577-585) widens the filter scope to the full collection while the builder-controlled $set body runs against every matched document. The authorized middleware at…
Recommended action: Upgrade to 3.39.12 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
POST /api/pwa/process-zip at packages/server/src/api/routes/static.ts:24 accepts a builder-uploaded .zip, extracts it with extract-zip@2.0.1 into a temp directory, then for each entry listed in icons.json validates the icon path, opens it, and streams the bytes into MinIO. The resulting object is served back via GET /api/assets/{appId}/pwa/{uuid}.png. extract-zip@2.0.1 preserves absolute symlink targets when restoring symlink entries. The icon-source validator at packages/server/src/api/controllers/static/index.ts:259-268 resolves the icon source string against baseDir (path.resolve), checks resolvedSrc.startsWith(baseDir + path.sep) against that string, and calls fs.existsSync(resolvedSrc) which follows symbolic links to confirm the target exists. None of the three calls reject symbolic-link entries, so an entry stored at baseDir/evil.png but pointing at /data/.env passes the gate. packages/backend-core/src/objectStore/objectStore.ts:302 then calls (await…
Recommended action: Upgrade to 3.39.9 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The webhook trigger endpoint in Budibase is publicly accessible and passes the full HTTP request body into automation execution parameters. A mass assignment vulnerability in externalTrigger() allows an attacker to overwrite the internal appId property by including it in the webhook POST body. When the automation is processed asynchronously (the default path for webhooks without a collect step), the worker executes the attacker-defined automation in the context of the victim's workspace, granting full read/write access to the victim's database. Details The webhook trigger route is registered as a public endpoint with no authentication: The controller passes the raw request body as fields alongside the server-derived appId: In externalTrigger(), for webhook-triggered automations, params.fields is spread back into params: Because params.fields is spread after params, any key in the attacker's body overwrites the corresponding property in params. An attacker including "appId":…
Recommended action: Upgrade to 3.39.9 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The Budibase server route POST /api/attachments/:datasourceId/url (packages/server/src/api/routes/static.ts) is registered with only the recaptcha middleware. There is no authorized(...) middleware in the chain. The controller (packages/server/src/api/controllers/static/index.ts::getSignedUploadURL) looks the requested datasource up, instantiates an AWS S3 client with the datasource's stored accessKeyId / secretAccessKey, and returns an AWS Signature V4 pre-signed PutObjectCommand URL for the caller-supplied bucket and key. The bucket is not pinned to the datasource's configured bucket. The workspace context required by sdk.datasources.get is sourced by getWorkspaceIdFromCtx (packages/backend-core/src/utils/utils.ts) from any of: the x-budibase-app-id header, the JSON body appId, a path segment that begins with the workspace prefix, or ?appId=. auth.buildAuthMiddleware([], { publicAllowed: true }) runs before any of this and explicitly allows anonymous requests. The…
Recommended action: Upgrade to 3.39.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The application server exposes an unauthenticated endpoint that generates S3 PutObject presigned URLs using credentials stored in a workspace datasource. The route is protected only by the recaptcha middleware and does not require authentication, table permission, datasource permission, or builder access. A public caller who knows a workspace ID and S3 datasource ID can request a signed upload URL for attacker-controlled bucket and key values. Details The static route registers the signed upload URL endpoint with only recaptcha before the controller: - packages/server/src/api/routes/static.ts:44-48 The controller loads the datasource by datasourceId with enriched secret values: - packages/server/src/api/controllers/static/index.ts:590-598 The request body controls bucket and key, and the server signs a PUT URL using the stored datasource credentials: - packages/server/src/api/controllers/static/index.ts:609-629 The endpoint returns the signed URL and public URL to the caller: -…
Recommended action: Upgrade to 3.39.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Title Chat Identity Link Hijacking — Attacker Can Silently Map Their Slack/Discord Identity to Any Authenticated Budibase User's Account Severity High — CVSS 3.1: AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N = 7.3 Affected Product - Product: Budibase - Version: 3.37.2 (introduced in this version) - Component: packages/server/src/api/controllers/ai/chatIdentityLinks.ts - Endpoint: GET /api/chat-links/:instance/:token/handoff Vulnerability Type - CWE-352: Cross-Site Request Forgery - CWE-284: Improper Access Control --- Vulnerability Description GET /api/chat-links/:instance/:token/handoff is a public endpoint (no auth required) that performs a permanent, state-changing operation: it binds an external chat identity (Slack/Discord/MS Teams) to an authenticated Budibase user account, with no consent UI and no CSRF protection. The session token in the URL is created by the attacker (from their own /link slash command) and embeds the attacker's externalUserId. When an authenticated Budibase victim…
Recommended action: Upgrade to 3.39.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
fetchToken in the OAuth2 SDK makes a POST to a builder-supplied URL with plain node-fetch, skipping the blacklist.isBlacklisted check that every other outbound fetch path in the codebase uses. The Joi schema for the OAuth2 URL has no scheme or host restriction. Alice, a builder, points an OAuth2 config at http://169.254.169.254/... or http://127.0.0.1:5984/; the server connects and returns response-body fragments in the validation result. Details packages/server/src/sdk/workspace/oauth2/utils.ts:17-65 defines fetchToken. Near the end: config.url is whatever the builder stored. fetchConfig has redirect: "follow" (the default), so a public URL that returns 302 to an internal target is also reachable. The route validation at packages/server/src/api/routes/oauth2.ts:9 accepts any string: The controller passes the URL into fetchToken through crud.ts. The /api/oauth2/validate endpoint (builder role) is the most direct attack path: it lives on builderRoutes, takes the URL from the…
Recommended action: Upgrade to 3.39.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Budibase stores external REST datasource credentials server-side and documents that database credentials are applied server-side and are not exposed in the UI. The REST datasource implementation redacts stored Basic/Bearer/OAuth2 auth secrets before returning datasource data to clients. However, the single-datasource GET and PUT routes are guarded by generic TABLE READ, not by Builder/Admin permission or datasource-specific ownership/resource checks. The built-in Basic app user role maps to the WRITE permission set, which includes table read/write and query write. A Basic user can therefore read an existing REST datasource, receive redacted authConfigs values, submit an update that changes only config.url while keeping the redacted placeholders, and trigger an existing saved relative-path REST query. During update, mergeConfigs() restores the old stored secret when it sees the redaction placeholder. During query execution, Budibase prefixes the attacker-controlled datasource…
Recommended action: Upgrade to 3.39.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The webhook schema-building endpoint is registered under builderRoutes, but the generic authorization middleware skips authorization for all paths matching /api/webhooks/schema. As a result, an unauthenticated caller can update the body schema for a known webhook and mutate the corresponding automation trigger output schema. Details The route appears to be builder-only: - packages/server/src/api/routes/webhook.ts:5-9 However, webhook endpoint detection explicitly includes schema: - packages/server/src/middleware/utils.ts:3-9 The authorization middleware bypasses all webhook endpoints before checking ctx.user or permissions: - packages/server/src/middleware/authorized.ts:90-99 The bypassed controller writes attacker-derived schema data to the webhook and automation trigger outputs: - packages/server/src/api/controllers/webhook.ts:56-83 The route grouping suggests builder authorization was intended, but the global webhook bypass removes it. PoC Non-destructive validation approach: 1.…
Recommended action: Upgrade to 3.39.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
/api/public/v1/roles/assign is guarded by the builderOrAdmin middleware, which passes any user who is a builder for the app id in the x-budibase-app-id header. That check admits both global builders and workspace-scoped builders (builder.apps set but builder.global unset). The controller then spreads the request body into the SDK call, and the SDK grants builder.global=true or admin.global=true on whichever user ids the caller supplies. Bob, a workspace-scoped builder with an API key, promotes himself or any other user to global admin with one POST. The whole flow is tenant-wide privilege escalation from an app-level role, available to anyone with an Enterprise license that unlocks the EXPANDEDPUBLICAPI feature. Details Controller (packages/server/src/api/controllers/public/roles.ts:13-17): Nothing filters assignmentProps. The request body's builder and admin keys flow directly into the SDK. SDK (packages/pro/src/sdk/publicApi/roles.ts:17-47): No check that the caller already…
Recommended action: Upgrade to 3.39.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The VectorDB configuration endpoint in Budibase accepts a host parameter that undergoes no validation against internal IP ranges, reserved hostnames, or URL schemes. Any authenticated user with builder-level access can supply an arbitrary host value such as 169.254.169.254 or localhost, causing the server to initiate outbound TCP connections to internal network addresses or cloud metadata endpoints on their behalf. Details The validator responsible for VectorDB creation and updates defines the host field as Joi.string().required(), which enforces only that the value is a non-empty string. No allowlist of external hostnames, no blocklist of RFC 1918 or link-local ranges, and no scheme validation are applied before the value is forwarded to the database SDK for connection establishment. When a VectorDB entry is created or updated, the SDK uses the supplied host directly to open a TCP connection. Because the connection attempt originates from the Budibase server process, it…
Recommended action: Upgrade to 3.35.3 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The OAuth2 token fetch function in packages/server/src/sdk/workspace/oauth2/utils.ts (line 59) uses raw fetch(config.url) with no SSRF protection. The safe wrapper fetchWithBlacklist() exists in the same codebase and is used in every other outbound HTTP call (automation steps, plugin downloads, object store), but was not applied to the OAuth2 token endpoint. A user with BUILDER role can point the OAuth2 token URL to internal services (CouchDB, cloud metadata) to exfiltrate sensitive data. Details Vulnerable code — packages/server/src/sdk/workspace/oauth2/utils.ts:59: Safe wrapper used everywhere else — packages/backend-core/src/utils/outboundFetch.ts: Where fetchWithBlacklist IS used (consistency gap proof): - automations/steps/discord.ts — Discord webhook - automations/steps/slack.ts — Slack webhook - automations/steps/make.ts — Make.com integration - automations/steps/n8n.ts — n8n integration - automations/steps/zapier.ts — Zapier integration -…
Recommended action: Upgrade to 3.39.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Security Advisory: CouchDB Reduce Injection via Unsanitized Calculation Parameter in V1 Views API Affected Software: Budibase Affected Component: packages/server/src/api/controllers/view/viewBuilder.ts, packages/server/src/api/routes/view.ts CWE: CWE-94 (Improper Control of Generation of Code) Discovery Date: 2026-03-24 --- Summary The V1 Views API (POST /api/views) accepts a calculation parameter from the request body that is interpolated directly into a CouchDB reduce function definition without validation. Although an internal SCHEMAMAP object defines the valid calculation types (sum, count, stats), no actual validation is performed against this map before the value is used in string interpolation. A user with Builder permissions can inject arbitrary JavaScript code that will be executed within the CouchDB JavaScript engine when the view is queried. --- Affected Component Route: POST /api/views (V1 legacy views endpoint) File: packages/server/src/api/routes/view.ts, line 45 Note:…
Recommended action: Upgrade to 3.38.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Budibase exposes a REST API for datasource management. The route PUT /api/datasources/:datasourceId is registered in the authorizedRoutes group with TABLE/READ permission. This is the same authorization level as the read endpoint (GET /api/datasources/:datasourceId). Every authenticated Budibase app user with the BASIC built-in role or higher carries TABLE/WRITE (and therefore TABLE/READ) permissions, and the datasource update controller performs no additional builder check. As a result, any authenticated non-builder app user can submit a PUT request to rewrite a datasource's config object — including the connection host, port, database credentials, or the base url of a REST datasource. Because no network-level SSRF protection is applied to SQL driver connections, redirecting a PostgreSQL/MySQL/MongoDB datasource to an internal IP address succeeds and the attacker can probe or interact with internal services on arbitrary ports. Code evidence Route registration — wrong…
Recommended action: Upgrade to 3.38.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The REST datasource integration follows HTTP redirects without re-checking the IP blacklist, allowing an authenticated Builder to access internal services (cloud metadata, databases) by redirecting through an attacker-controlled server. The same vulnerability class was already patched in automation steps (fetchWithBlacklist in packages/server/src/automations/steps/utils.ts) but the REST integration was missed. Details Vulnerable file: packages/server/src/integrations/rest.ts, lines 754-778 The req() method checks the request URL against the IP blacklist at line 754, then calls fetch(url, input) at line 778. No redirect: "manual" option is set, so undici's fetch defaults to redirect: "follow", automatically following HTTP 301/302/307 redirects without re-validating the redirect target against the blacklist. The automation steps already implement the correct fix in packages/server/src/automations/steps/utils.ts (lines 100-136) via fetchWithBlacklist(), which sets redirect:…
Recommended action: Upgrade to 3.38.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Vulnerability Details CWE-918: Server-Side Request Forgery (SSRF) The processUrlFile function in packages/server/src/automations/steps/ai/extract.ts uses fetch(fileUrl) directly without the IP blacklist validation that is consistently applied to all other automation steps. This allows an authenticated user to trigger server-side requests to internal network addresses. Vulnerable Code packages/server/src/automations/steps/ai/extract.ts (lines 116, 139): Contrast with All Other Automation Steps (Same Codebase) Every other automation step that makes outbound HTTP requests properly uses fetchWithBlacklist: - steps/slack.ts:19: response = await fetchWithBlacklist(url, {...}) - steps/discord.ts:28: response = await fetchWithBlacklist(url, {...}) - steps/zapier.ts:33: response = await fetchWithBlacklist(url, {...}) - steps/n8n.ts:53: response = await fetchWithBlacklist(url, request) - steps/outgoingWebhook.ts: response = await fetchWithBlacklist(url, {...}) - steps/make.ts: response = await…
Recommended action: Upgrade to 3.34.8 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
An unauthenticated attacker can achieve Remote Code Execution (RCE) on the Budibase server by triggering an automation that contains a Bash step via the public webhook endpoint. No authentication is required to trigger the exploit. The process executes as root inside the container. Details Vulnerable endpoint — packages/server/src/api/routes/webhook.ts line 13: The webhook trigger endpoint is registered on publicRoutes with no authentication middleware. Any unauthenticated HTTP client can POST to this endpoint. Vulnerable sink — packages/server/src/automations/steps/bash.ts lines 21–26: The Bash automation step uses Handlebars template processing (processStringSync) on inputs.code, substituting values from the webhook request body into the shell command string before passing it to execSync(). Attack chain: Precondition: An admin must have created and published an automation containing: 1. A Webhook trigger 2. A Bash step whose code field uses a trigger field template (e.g.,…
Recommended action: Upgrade to 3.33.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
The plugin file upload endpoint (POST /api/plugin/upload) passes the user-supplied filename directly to createTempFolder() without sanitizing path traversal sequences. An attacker with Global Builder privileges can craft a multipart upload with a filename containing ../ to delete arbitrary directories via rmSync and write arbitrary files via tarball extraction to any filesystem path the Node.js process can access. Severity - Attack Vector: Network — exploitable via the plugin upload HTTP API - Attack Complexity: Low — no special conditions; a single crafted multipart request suffices - Privileges Required: High — requires Global Builder role (GLOBALBUILDER permission) - User Interaction: None - Scope: Changed — the plugin upload feature is scoped to a temp directory, but the traversal escapes to the host filesystem - Confidentiality Impact: None — the vulnerability enables deletion and writing, not reading - Integrity Impact: High — attacker can delete arbitrary directories…
Recommended action: Upgrade to 3.33.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Location: packages/server/src/automations/steps/bash.ts Description The bash automation step executes user-provided commands using execSync without proper sanitization or validation. User input is processed through processStringSync which allows template interpolation, potentially allowing arbitrary command execution. Code Reference Attack Vector An attacker with access to create or modify automations can inject malicious shell commands by including template syntax that evaluates to command injection payloads (e.g., $(rm -rf /), ; malicious-command, | malicious-command). Impact - Remote code execution (RCE) - Complete system compromise - Data exfiltration - Lateral movement within the infrastructure Recommendation 1. Immediate: Disable bash automation step in production until fixed 2. Implement a whitelist of allowed commands 3. Use parameterized command execution with proper escaping 4. Implement command argument validation 5. Consider using a restricted shell or command sandboxing…
Recommended action: Upgrade to 3.33.4 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Location: packages/server/src/integrations/postgres.ts:529-531 Description The PostgreSQL integration constructs shell commands using user-controlled configuration values (database name, host, password, etc.) without proper sanitization. The password and other connection parameters are directly interpolated into a shell command. Code Reference Attack Vector An attacker who can control database configuration values (e.g., through compromised credentials or configuration injection) can inject shell commands. For example: - Password: password"; malicious-command; echo " - Database name: db"; rm -rf /; echo " Impact - Remote code execution - System compromise - Data exfiltration Recommendation 1. Use environment variables for sensitive values instead of command-line arguments 2. Validate and sanitize all configuration values 3. Use proper escaping for shell arguments 4. Consider using a PostgreSQL library's native dump functionality instead of shell commands Example Fix
Recommended action: Upgrade to 3.23.32 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.
Impact Previously, budibase used a library called vm2 for code execution inside the Budibase builder and apps, such as the UI below for configuring bindings in the design section. Due to a vulnerability in vm2, any environment that executed the code server side (automations and column formulas) was susceptible to this vulnerability, allowing users to escape the sandbox provided by vm2, and to expose server side variables such as process.env. It's recommended by the authors of vm2 themselves that you should move to another solution for remote JS execution due to this vulnerability. Patches We moved our entire JS sandbox infrastructure over to isolated-vm, a much more secure and recommended library for remote code execution in 2.20.0. This also comes with a performance benefit in the way we cache and execute your JS server side. The budibase cloud platform has been patched already and is not running vm2, but self host users will need to manage the updates by themselves. If you are a…
Recommended action: Upgrade to 2.20.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.