CWE-863
Allowed-with-ReviewIncorrect Authorization
Abstraction: Class · Status: Incomplete
The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.
6038 vulnerabilities reference this CWE, most recent first.
GHSA-XCW2-CX77-J362
Vulnerability from github – Published: 2025-09-04 21:31 – Updated: 2025-09-05 18:31In onCreate of SelectAccountActivity.java, there is a possible way to add contacts without permission due to a logic error in the code. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.
{
"affected": [],
"aliases": [
"CVE-2025-48523"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-09-04T19:15:38Z",
"severity": "HIGH"
},
"details": "In onCreate of SelectAccountActivity.java, there is a possible way to add contacts without permission due to a logic error in the code. This could lead to local escalation of privilege with no additional execution privileges needed. User interaction is not needed for exploitation.",
"id": "GHSA-xcw2-cx77-j362",
"modified": "2025-09-05T18:31:19Z",
"published": "2025-09-04T21:31:38Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-48523"
},
{
"type": "WEB",
"url": "https://android.googlesource.com/platform/packages/apps/Contacts/+/7c8dbcffbc9382fcdb788919106c3b0525db83ab"
},
{
"type": "WEB",
"url": "https://source.android.com/security/bulletin/2025-09-01"
}
],
"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-XCX6-4F2G-HHGX
Vulnerability from github – Published: 2026-07-24 21:17 – Updated: 2026-07-24 21:17Impact
In Budibase v3.39.4, a regression in the authorization level for the S3 attachment upload endpoint allows any BASIC app user to obtain S3 PutObject presigned URLs. The endpoint uses TABLE/WRITE permission level instead of the intended BUILDER level defined in v3.39.3. Additionally, the controller does not pin the target bucket to the datasource's configured bucket, allowing writes to any S3 bucket the stored IAM credentials can access.
Reproduction
- As a BASIC app user, discover or obtain a valid S3 datasource ID within the app
- Send a POST request:
POST /api/attachments/<datasourceId>/url
Content-Type: application/json
x-budibase-app-id: <appId>
{"bucket": "target-bucket", "key": "malicious-file.html"}
- The response contains a valid S3 PutObject presigned URL
- Use the presigned URL to upload arbitrary content to any writable S3 bucket in the IAM credential scope
Root Cause
The /api/attachments/:datasourceId/url route was changed from authorized(BUILDER) in v3.39.3 to authorized(PermissionType.TABLE, PermissionLevel.WRITE) in v3.39.4. BASIC users have TABLE/WRITE permissions by default, so they can call this endpoint. The controller at packages/server/src/api/controllers/static/index.ts:614-632 accepts the bucket parameter directly from the request body and passes it to getSignedUrl without validating against the datasource's configured bucket.
Evidence
The test suite at packages/server/src/api/routes/tests/static.spec.ts:218-235 confirms this behavior. The test authenticates as a BASIC role user and successfully generates a signed upload URL, verifying HTTP 200 and a defined res.body.signedUrl.
Remediation
- Restore the
authorized(BUILDER)middleware on the route - Add
paramResource("datasourceId")to ensure the datasource belongs to the caller's app - Pin the S3 bucket to
datasource.config.bucketin the controller, ignoring the caller-supplied bucket value
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "@budibase/server"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "3.38.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-24T21:17:03Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "## Impact\n\nIn Budibase v3.39.4, a regression in the authorization level for the S3 attachment upload endpoint allows any BASIC app user to obtain S3 PutObject presigned URLs. The endpoint uses TABLE/WRITE permission level instead of the intended BUILDER level defined in v3.39.3. Additionally, the controller does not pin the target bucket to the datasource\u0027s configured bucket, allowing writes to any S3 bucket the stored IAM credentials can access.\n\n## Reproduction\n\n1. As a BASIC app user, discover or obtain a valid S3 datasource ID within the app\n2. Send a POST request:\n\n```\nPOST /api/attachments/\u003cdatasourceId\u003e/url\nContent-Type: application/json\nx-budibase-app-id: \u003cappId\u003e\n\n{\"bucket\": \"target-bucket\", \"key\": \"malicious-file.html\"}\n```\n\n3. The response contains a valid S3 PutObject presigned URL\n4. Use the presigned URL to upload arbitrary content to any writable S3 bucket in the IAM credential scope\n\n## Root Cause\n\nThe `/api/attachments/:datasourceId/url` route was changed from `authorized(BUILDER)` in v3.39.3 to `authorized(PermissionType.TABLE, PermissionLevel.WRITE)` in v3.39.4. BASIC users have TABLE/WRITE permissions by default, so they can call this endpoint. The controller at `packages/server/src/api/controllers/static/index.ts:614-632` accepts the `bucket` parameter directly from the request body and passes it to `getSignedUrl` without validating against the datasource\u0027s configured bucket.\n\n## Evidence\n\nThe test suite at `packages/server/src/api/routes/tests/static.spec.ts:218-235` confirms this behavior. The test authenticates as a BASIC role user and successfully generates a signed upload URL, verifying HTTP 200 and a defined `res.body.signedUrl`.\n\n## Remediation\n\n1. Restore the `authorized(BUILDER)` middleware on the route\n2. Add `paramResource(\"datasourceId\")` to ensure the datasource belongs to the caller\u0027s app\n3. Pin the S3 bucket to `datasource.config.bucket` in the controller, ignoring the caller-supplied bucket value",
"id": "GHSA-xcx6-4f2g-hhgx",
"modified": "2026-07-24T21:17:03Z",
"published": "2026-07-24T21:17:03Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Budibase/budibase/security/advisories/GHSA-xcx6-4f2g-hhgx"
},
{
"type": "PACKAGE",
"url": "https://github.com/Budibase/budibase"
},
{
"type": "WEB",
"url": "https://github.com/Budibase/budibase/releases/tag/3.40.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": " Budibase: S3 presigned URL endpoint authorization regression in v3.39.4 allows BASIC users to obtain S3 PutObject presigned URLs"
}
GHSA-XF3P-Q42R-RWGF
Vulnerability from github – Published: 2023-12-05 03:30 – Updated: 2023-12-05 03:30Improper Authentication vulnerability in Samsung Pass prior to version 4.3.00.17 allows physical attackers to bypass authentication due to invalid flag setting.
{
"affected": [],
"aliases": [
"CVE-2023-42575"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-12-05T03:15:18Z",
"severity": "MODERATE"
},
"details": "Improper Authentication vulnerability in Samsung Pass prior to version 4.3.00.17 allows physical attackers to bypass authentication due to invalid flag setting.",
"id": "GHSA-xf3p-q42r-rwgf",
"modified": "2023-12-05T03:30:23Z",
"published": "2023-12-05T03:30:23Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-42575"
},
{
"type": "WEB",
"url": "https://security.samsungmobile.com/serviceWeb.smsb?year=2023\u0026month=12"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:P/AC:L/PR:H/UI:R/S:U/C:H/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-XF7M-V66Q-76W8
Vulnerability from github – Published: 2025-11-01 03:30 – Updated: 2025-11-15 02:24Blogs in Liferay Portal 7.4.0 through 7.4.3.111, and older unsupported versions, and Liferay DXP 2023.Q4.0 through 2023.Q4.10, 2023.Q3.1 through 2023.Q3.10, 7.4 GA through update 92, and older unsupported versions does not check permission of images in a blog entry, which allows remote attackers to view the images in a blog entry via crafted URL.
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "com.liferay:com.liferay.blogs.item.selector.web"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "6.0.19"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-62275"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2025-11-03T21:06:57Z",
"nvd_published_at": "2025-11-01T03:15:31Z",
"severity": "MODERATE"
},
"details": "Blogs in Liferay Portal 7.4.0 through 7.4.3.111, and older unsupported versions, and Liferay DXP 2023.Q4.0 through 2023.Q4.10, 2023.Q3.1 through 2023.Q3.10, 7.4 GA through update 92, and older unsupported versions does not check permission of images in a blog entry, which allows remote attackers to view the images in a blog entry via crafted URL.",
"id": "GHSA-xf7m-v66q-76w8",
"modified": "2025-11-15T02:24:51Z",
"published": "2025-11-01T03:30:24Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-62275"
},
{
"type": "WEB",
"url": "https://github.com/liferay/liferay-portal/commit/9856c55bcbb3b8ce1276117709b9c0082a19c62c"
},
{
"type": "WEB",
"url": "https://github.com/liferay/liferay-portal/commit/e0ae29cfdb8d10a6fddc56d04ca3ae88c3fbc7f3"
},
{
"type": "PACKAGE",
"url": "https://github.com/liferay/liferay-portal"
},
{
"type": "WEB",
"url": "https://liferay.atlassian.net/browse/LPE-17948"
},
{
"type": "WEB",
"url": "https://liferay.dev/portal/security/known-vulnerabilities/-/asset_publisher/jekt/content/CVE-2025-62275"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Liferay Portal and DXP do not check permissions of images in a blog entry"
}
GHSA-XFC5-HP99-89QR
Vulnerability from github – Published: 2022-05-24 17:45 – Updated: 2022-05-24 17:45The team sync HTTP API in Grafana Enterprise 7.4.x before 7.4.5 has an Incorrect Access Control issue. On Grafana instances using an external authentication service, this vulnerability allows any authenticated user to add external groups to existing teams. This can be used to grant a user team permissions that the user isn't supposed to have.
{
"affected": [],
"aliases": [
"CVE-2021-28146"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-03-22T14:15:00Z",
"severity": "MODERATE"
},
"details": "The team sync HTTP API in Grafana Enterprise 7.4.x before 7.4.5 has an Incorrect Access Control issue. On Grafana instances using an external authentication service, this vulnerability allows any authenticated user to add external groups to existing teams. This can be used to grant a user team permissions that the user isn\u0027t supposed to have.",
"id": "GHSA-xfc5-hp99-89qr",
"modified": "2022-05-24T17:45:03Z",
"published": "2022-05-24T17:45:03Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-28146"
},
{
"type": "WEB",
"url": "https://community.grafana.com/t/grafana-enterprise-6-7-6-7-3-10-and-7-4-5-security-update/44724"
},
{
"type": "WEB",
"url": "https://community.grafana.com/t/release-notes-v6-7-x/27119"
},
{
"type": "WEB",
"url": "https://grafana.com/blog/2021/03/18/grafana-6.7.6-7.3.10-and-7.4.5-released-with-important-security-fixes-for-grafana-enterprise"
},
{
"type": "WEB",
"url": "https://grafana.com/docs/grafana/latest/release-notes/release-notes-7-3-10"
},
{
"type": "WEB",
"url": "https://grafana.com/docs/grafana/latest/release-notes/release-notes-7-4-5"
},
{
"type": "WEB",
"url": "https://grafana.com/products/enterprise"
},
{
"type": "WEB",
"url": "https://www.openwall.com/lists/oss-security/2021/03/19/5"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-XFCW-6C56-RP9P
Vulnerability from github – Published: 2022-05-24 17:45 – Updated: 2022-08-13 00:00Using PendingIntent with implicit intent in Bixby Voice prior to version 3.0.52.14 allows attackers to execute privileged action by hijacking and modifying the intent.
{
"affected": [],
"aliases": [
"CVE-2021-25352"
],
"database_specific": {
"cwe_ids": [
"CWE-668",
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-03-25T17:15:00Z",
"severity": "HIGH"
},
"details": "Using PendingIntent with implicit intent in Bixby Voice prior to version 3.0.52.14 allows attackers to execute privileged action by hijacking and modifying the intent.",
"id": "GHSA-xfcw-6c56-rp9p",
"modified": "2022-08-13T00:00:33Z",
"published": "2022-05-24T17:45:24Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-25352"
},
{
"type": "WEB",
"url": "https://security.samsungmobile.com"
},
{
"type": "WEB",
"url": "https://security.samsungmobile.com/serviceWeb.smsb"
}
],
"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-XFF3-5C9P-2MR4
Vulnerability from github – Published: 2026-04-24 15:43 – Updated: 2026-05-13 13:37Summary
A critical vulnerability exists in the Stripe webhook handler that allows an unauthenticated attacker to forge webhook events and credit arbitrary quota to their account without making any payment. The vulnerability stems from three compounding flaws:
- The Stripe webhook endpoint does not reject requests when
StripeWebhookSecretis empty (the default). - When the HMAC secret is empty, any attacker can compute valid webhook signatures, effectively bypassing signature verification entirely.
- The
Rechargefunction does not validate that the order'sPaymentMethodmatches the callback source, enabling cross-gateway exploitation — an order created via any payment method (e.g., Epay) can be fulfilled through a forged Stripe webhook.
Affected Components
controller/topup_stripe.go—StripeWebhook(),sessionCompleted()model/topup.go—Recharge(),RechargeCreem(),RechargeWaffo()controller/topup.go—EpayNotify()controller/topup_creem.go—CreemAdaptor.RequestPay()(missingPaymentMethodfield)router/api-router.go— webhook route registered without any guard
CWE Classification
- CWE-345: Insufficient Verification of Data Authenticity
- CWE-1188: Initialization with an Insecure Default (empty webhook secret)
- CWE-863: Incorrect Authorization (cross-gateway order fulfillment)
Vulnerability Details
Flaw 1: Empty Webhook Secret Bypasses Signature Verification
The StripeWebhookSecret setting defaults to an empty string "". The Stripe Go SDK (webhook.ConstructEventWithOptions) does not reject empty secrets — it computes HMAC-SHA256 with an empty key, producing a deterministic and publicly computable signature.
Vulnerable code (controller/topup_stripe.go):
func StripeWebhook(c *gin.Context) {
// No check for empty StripeWebhookSecret
payload, _ := io.ReadAll(c.Request.Body)
signature := c.GetHeader("Stripe-Signature")
endpointSecret := setting.StripeWebhookSecret // defaults to ""
event, err := webhook.ConstructEventWithOptions(payload, signature, endpointSecret, ...)
// When secret is "", attacker can compute valid HMAC with the same empty key
}
The webhook route is unconditionally registered with no authentication middleware and no rate limiting:
apiRouter.POST("/stripe/webhook", controller.StripeWebhook)
Flaw 2: Missing payment_status Verification
The sessionCompleted handler only checks status == "complete" but does not verify payment_status == "paid". Stripe's checkout.session.completed event can fire with payment_status = "unpaid" for delayed payment methods (bank transfer, SEPA, Boleto, etc.) or payment_status = "no_payment_required" for 100% discount coupons.
Additionally, checkout.session.async_payment_succeeded and checkout.session.async_payment_failed events are not handled, so delayed payments that ultimately fail are never rolled back.
Flaw 3: Cross-Gateway Order Fulfillment (No PaymentMethod Validation)
The model.Recharge() function (called by the Stripe webhook) looks up orders solely by trade_no and does not validate that the order's PaymentMethod is "stripe":
func Recharge(referenceId string, customerId string) (err error) {
// Finds ANY pending order by trade_no, regardless of PaymentMethod
tx.Where("trade_no = ?", referenceId).First(topUp)
if topUp.Status != "pending" { return }
// Credits quota without checking topUp.PaymentMethod
quota = topUp.Money * QuotaPerUnit
tx.Model(&User{}).Update("quota", gorm.Expr("quota + ?", quota))
}
This allows an attacker to create orders through any configured payment gateway (Epay, Creem, Waffo) and then complete them via a forged Stripe webhook — even if Stripe itself was never configured.
Attack Scenario
Prerequisites: Any payment method is configured (e.g., Epay) + StripeWebhookSecret is empty (default).
- Attacker registers a user account.
- Attacker calls
POST /api/user/payto create an Epay top-up order (e.g.,amount=10000). The order is stored withstatus=pending. - Attacker queries
GET /api/user/topup/selfto retrieve thetrade_noof the pending order. - Attacker computes
HMAC-SHA256with an empty key over a craftedcheckout.session.completedpayload containing the stolentrade_noasclient_reference_id. - Attacker sends
POST /api/stripe/webhookwith the forged payload and signature header. - The server verifies the signature (passes because the secret is empty), calls
Recharge(), which finds the Epay order bytrade_no, marks it assuccess, and credits the full quota. - Attacker repeats steps 2–6 indefinitely for unlimited credits.
Proof of concept (pseudocode):
import hmac, hashlib, time, json, requests
timestamp = int(time.time())
payload = json.dumps({
"type": "checkout.session.completed",
"data": {
"object": {
"client_reference_id": "<trade_no from step 3>",
"status": "complete",
"payment_status": "paid",
"customer": "cus_fake",
"amount_total": "0",
"currency": "usd"
}
}
})
# Empty secret = publicly computable signature
sig = hmac.new(b"", f"{timestamp}.{payload}".encode(), hashlib.sha256).hexdigest()
header = f"t={timestamp},v1={sig}"
requests.post("https://target/api/stripe/webhook",
data=payload,
headers={"Stripe-Signature": header, "Content-Type": "application/json"})
Remediation
Fix 1: Reject webhooks when secret is empty
func StripeWebhook(c *gin.Context) {
if setting.StripeWebhookSecret == "" {
c.AbortWithStatus(http.StatusForbidden)
return
}
// ... existing logic
}
Fix 2: Verify payment_status and handle async payment events
func sessionCompleted(event stripe.Event) {
// ... existing status check ...
paymentStatus := event.GetObjectValue("payment_status")
if paymentStatus != "paid" {
return // Wait for async_payment_succeeded event
}
fulfillOrder(event, referenceId, customerId)
}
Add handlers for checkout.session.async_payment_succeeded and checkout.session.async_payment_failed.
Fix 3: Validate PaymentMethod in all recharge functions
// In model.Recharge (Stripe):
if topUp.PaymentMethod != "stripe" {
return ErrPaymentMethodMismatch
}
// In model.RechargeCreem:
if topUp.PaymentMethod != "creem" {
return ErrPaymentMethodMismatch
}
// In model.RechargeWaffo:
if topUp.PaymentMethod != "waffo" {
return ErrPaymentMethodMismatch
}
// In controller.EpayNotify:
if topUp.PaymentMethod == "stripe" || topUp.PaymentMethod == "creem" || topUp.PaymentMethod == "waffo" {
return // reject cross-gateway fulfillment
}
Additional fix: Set PaymentMethod on Creem order creation
The Creem order creation was missing the PaymentMethod field entirely:
topUp := &model.TopUp{
// ...
PaymentMethod: "creem", // was missing
}
Patched Versions
- v0.12.10 — includes all three fixes described above.
All users are strongly encouraged to upgrade immediately.
Workaround (for users unable to upgrade immediately)
If users cannot upgrade to v0.12.10 right away, apply all of the following mitigations:
-
Set
StripeWebhookSecretto any non-empty value. Go to the admin panel → Payment → Stripe, and set the Webhook Signing Secret to any random string (e.g.,whsec_placeholder_do_not_leave_empty). It does not need to be a real Stripe secret — any non-empty value will prevent the empty-key HMAC forgery. This is the single most important step — it closes the primary attack vector. If Stripe payments are used in production, replace with the real secret from the project's Stripe Dashboard → Webhooks to ensure legitimate webhooks continue to work. -
If Stripe is not in use, block the webhook endpoint. If users have not configured Stripe payments, use a reverse proxy (Nginx, Caddy, etc.) to deny access to
/api/stripe/webhook:nginx location = /api/stripe/webhook { return 403; }
Note: The workaround only mitigates Flaw 1 (empty secret bypass). Flaws 2 (missing
payment_statuscheck) and 3 (cross-gateway fulfillment) are only fully addressed in v0.12.10. Upgrading is the only complete fix.
Impact
- Financial fraud: Attacker obtains unlimited API quota without payment.
- Operator financial loss: Fraudulent quota is consumed against upstream AI providers (OpenAI, Anthropic, Google, etc.), charged to the operator.
- Silent exploitation: Fraudulent top-ups appear as normal successful transactions in system logs, making detection difficult.
- Wide exposure: The default insecure configuration means virtually all deployments with any payment method enabled are vulnerable.
Timeline
- 2025-04-15: Vulnerability reported by @ChangeYu0229
- 2025-04-15: Vulnerability confirmed and root cause analysis completed
- 2025-04-15: Fix developed and applied
- 2025-04-15: Patched in v0.12.10
Resources
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/QuantumNous/new-api"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.12.10"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41432"
],
"database_specific": {
"cwe_ids": [
"CWE-1188",
"CWE-345",
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-24T15:43:25Z",
"nvd_published_at": "2026-05-08T23:16:35Z",
"severity": "HIGH"
},
"details": "## Summary\n\nA critical vulnerability exists in the Stripe webhook handler that allows an **unauthenticated attacker to forge webhook events** and credit arbitrary quota to their account without making any payment. The vulnerability stems from three compounding flaws:\n\n1. The Stripe webhook endpoint does not reject requests when `StripeWebhookSecret` is empty (the default).\n2. When the HMAC secret is empty, any attacker can compute valid webhook signatures, effectively **bypassing signature verification entirely**.\n3. The `Recharge` function does not validate that the order\u0027s `PaymentMethod` matches the callback source, enabling **cross-gateway exploitation** \u2014 an order created via any payment method (e.g., Epay) can be fulfilled through a forged Stripe webhook.\n\n## Affected Components\n\n- `controller/topup_stripe.go` \u2014 `StripeWebhook()`, `sessionCompleted()`\n- `model/topup.go` \u2014 `Recharge()`, `RechargeCreem()`, `RechargeWaffo()`\n- `controller/topup.go` \u2014 `EpayNotify()`\n- `controller/topup_creem.go` \u2014 `CreemAdaptor.RequestPay()` (missing `PaymentMethod` field)\n- `router/api-router.go` \u2014 webhook route registered without any guard\n\n## CWE Classification\n\n- **CWE-345**: Insufficient Verification of Data Authenticity\n- **CWE-1188**: Initialization with an Insecure Default (empty webhook secret)\n- **CWE-863**: Incorrect Authorization (cross-gateway order fulfillment)\n\n## Vulnerability Details\n\n### Flaw 1: Empty Webhook Secret Bypasses Signature Verification\n\nThe `StripeWebhookSecret` setting defaults to an empty string `\"\"`. The Stripe Go SDK (`webhook.ConstructEventWithOptions`) does **not** reject empty secrets \u2014 it computes `HMAC-SHA256` with an empty key, producing a deterministic and publicly computable signature.\n\n**Vulnerable code** (`controller/topup_stripe.go`):\n```go\nfunc StripeWebhook(c *gin.Context) {\n // No check for empty StripeWebhookSecret\n payload, _ := io.ReadAll(c.Request.Body)\n signature := c.GetHeader(\"Stripe-Signature\")\n endpointSecret := setting.StripeWebhookSecret // defaults to \"\"\n event, err := webhook.ConstructEventWithOptions(payload, signature, endpointSecret, ...)\n // When secret is \"\", attacker can compute valid HMAC with the same empty key\n}\n```\n\nThe webhook route is unconditionally registered with **no authentication middleware and no rate limiting**:\n```go\napiRouter.POST(\"/stripe/webhook\", controller.StripeWebhook)\n```\n\n### Flaw 2: Missing `payment_status` Verification\n\nThe `sessionCompleted` handler only checks `status == \"complete\"` but does **not** verify `payment_status == \"paid\"`. Stripe\u0027s `checkout.session.completed` event can fire with `payment_status = \"unpaid\"` for delayed payment methods (bank transfer, SEPA, Boleto, etc.) or `payment_status = \"no_payment_required\"` for 100% discount coupons.\n\nAdditionally, `checkout.session.async_payment_succeeded` and `checkout.session.async_payment_failed` events are not handled, so delayed payments that ultimately fail are never rolled back.\n\n### Flaw 3: Cross-Gateway Order Fulfillment (No PaymentMethod Validation)\n\nThe `model.Recharge()` function (called by the Stripe webhook) looks up orders solely by `trade_no` and does **not** validate that the order\u0027s `PaymentMethod` is `\"stripe\"`:\n\n```go\nfunc Recharge(referenceId string, customerId string) (err error) {\n // Finds ANY pending order by trade_no, regardless of PaymentMethod\n tx.Where(\"trade_no = ?\", referenceId).First(topUp)\n if topUp.Status != \"pending\" { return }\n // Credits quota without checking topUp.PaymentMethod\n quota = topUp.Money * QuotaPerUnit\n tx.Model(\u0026User{}).Update(\"quota\", gorm.Expr(\"quota + ?\", quota))\n}\n```\n\nThis allows an attacker to create orders through **any** configured payment gateway (Epay, Creem, Waffo) and then complete them via a forged Stripe webhook \u2014 even if Stripe itself was never configured.\n\n## Attack Scenario\n\n**Prerequisites**: Any payment method is configured (e.g., Epay) + `StripeWebhookSecret` is empty (default).\n\n1. Attacker registers a user account.\n2. Attacker calls `POST /api/user/pay` to create an Epay top-up order (e.g., `amount=10000`). The order is stored with `status=pending`.\n3. Attacker queries `GET /api/user/topup/self` to retrieve the `trade_no` of the pending order.\n4. Attacker computes `HMAC-SHA256` with an empty key over a crafted `checkout.session.completed` payload containing the stolen `trade_no` as `client_reference_id`.\n5. Attacker sends `POST /api/stripe/webhook` with the forged payload and signature header.\n6. The server verifies the signature (passes because the secret is empty), calls `Recharge()`, which finds the Epay order by `trade_no`, marks it as `success`, and credits the full quota.\n7. Attacker repeats steps 2\u20136 indefinitely for unlimited credits.\n\n**Proof of concept** (pseudocode):\n```python\nimport hmac, hashlib, time, json, requests\n\ntimestamp = int(time.time())\npayload = json.dumps({\n \"type\": \"checkout.session.completed\",\n \"data\": {\n \"object\": {\n \"client_reference_id\": \"\u003ctrade_no from step 3\u003e\",\n \"status\": \"complete\",\n \"payment_status\": \"paid\",\n \"customer\": \"cus_fake\",\n \"amount_total\": \"0\",\n \"currency\": \"usd\"\n }\n }\n})\n# Empty secret = publicly computable signature\nsig = hmac.new(b\"\", f\"{timestamp}.{payload}\".encode(), hashlib.sha256).hexdigest()\nheader = f\"t={timestamp},v1={sig}\"\n\nrequests.post(\"https://target/api/stripe/webhook\",\n data=payload,\n headers={\"Stripe-Signature\": header, \"Content-Type\": \"application/json\"})\n```\n\n## Remediation\n\n### Fix 1: Reject webhooks when secret is empty\n```go\nfunc StripeWebhook(c *gin.Context) {\n if setting.StripeWebhookSecret == \"\" {\n c.AbortWithStatus(http.StatusForbidden)\n return\n }\n // ... existing logic\n}\n```\n\n### Fix 2: Verify `payment_status` and handle async payment events\n```go\nfunc sessionCompleted(event stripe.Event) {\n // ... existing status check ...\n paymentStatus := event.GetObjectValue(\"payment_status\")\n if paymentStatus != \"paid\" {\n return // Wait for async_payment_succeeded event\n }\n fulfillOrder(event, referenceId, customerId)\n}\n```\n\nAdd handlers for `checkout.session.async_payment_succeeded` and `checkout.session.async_payment_failed`.\n\n### Fix 3: Validate PaymentMethod in all recharge functions\n```go\n// In model.Recharge (Stripe):\nif topUp.PaymentMethod != \"stripe\" {\n return ErrPaymentMethodMismatch\n}\n\n// In model.RechargeCreem:\nif topUp.PaymentMethod != \"creem\" {\n return ErrPaymentMethodMismatch\n}\n\n// In model.RechargeWaffo:\nif topUp.PaymentMethod != \"waffo\" {\n return ErrPaymentMethodMismatch\n}\n\n// In controller.EpayNotify:\nif topUp.PaymentMethod == \"stripe\" || topUp.PaymentMethod == \"creem\" || topUp.PaymentMethod == \"waffo\" {\n return // reject cross-gateway fulfillment\n}\n```\n\n### Additional fix: Set PaymentMethod on Creem order creation\nThe Creem order creation was missing the `PaymentMethod` field entirely:\n```go\ntopUp := \u0026model.TopUp{\n // ...\n PaymentMethod: \"creem\", // was missing\n}\n```\n\n## Patched Versions\n\n- **v0.12.10** \u2014 includes all three fixes described above.\n\nAll users are strongly encouraged to upgrade immediately.\n\n## Workaround (for users unable to upgrade immediately)\n\nIf users cannot upgrade to v0.12.10 right away, apply **all** of the following mitigations:\n\n1. **Set `StripeWebhookSecret` to any non-empty value.** Go to the admin panel \u2192 Payment \u2192 Stripe, and set the Webhook Signing Secret to **any random string** (e.g., `whsec_placeholder_do_not_leave_empty`). It does **not** need to be a real Stripe secret \u2014 any non-empty value will prevent the empty-key HMAC forgery. **This is the single most important step** \u2014 it closes the primary attack vector. If Stripe payments are used in production, replace with the real secret from the project\u0027s [Stripe Dashboard \u2192 Webhooks](https://dashboard.stripe.com/webhooks) to ensure legitimate webhooks continue to work.\n\n2. **If Stripe is not in use, block the webhook endpoint.** If users have not configured Stripe payments, use a reverse proxy (Nginx, Caddy, etc.) to deny access to `/api/stripe/webhook`:\n ```nginx\n location = /api/stripe/webhook {\n return 403;\n }\n ```\n\n\u003e **Note**: The workaround only mitigates Flaw 1 (empty secret bypass). Flaws 2 (missing `payment_status` check) and 3 (cross-gateway fulfillment) are only fully addressed in v0.12.10. **Upgrading is the only complete fix.**\n\n## Impact\n\n- **Financial fraud**: Attacker obtains unlimited API quota without payment.\n- **Operator financial loss**: Fraudulent quota is consumed against upstream AI providers (OpenAI, Anthropic, Google, etc.), charged to the operator.\n- **Silent exploitation**: Fraudulent top-ups appear as normal successful transactions in system logs, making detection difficult.\n- **Wide exposure**: The default insecure configuration means virtually all deployments with any payment method enabled are vulnerable.\n\n## Timeline\n\n- **2025-04-15**: Vulnerability reported by [@ChangeYu0229](https://github.com/ChangeYu0229)\n- **2025-04-15**: Vulnerability confirmed and root cause analysis completed\n- **2025-04-15**: Fix developed and applied\n- **2025-04-15**: Patched in v0.12.10\n\n## Resources\n\n- [Stripe Webhook Signature Verification Docs](https://docs.stripe.com/webhooks#verify-official-libraries)\n- [Stripe Checkout Fulfillment Guide \u2014 Handle async payment methods](https://docs.stripe.com/checkout/fulfillment#async-payment-methods)\n- [CWE-345: Insufficient Verification of Data Authenticity](https://cwe.mitre.org/data/definitions/345.html)\n- [CWE-1188: Initialization with an Insecure Default](https://cwe.mitre.org/data/definitions/1188.html)",
"id": "GHSA-xff3-5c9p-2mr4",
"modified": "2026-05-13T13:37:29Z",
"published": "2026-04-24T15:43:25Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/QuantumNous/new-api/security/advisories/GHSA-xff3-5c9p-2mr4"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41432"
},
{
"type": "WEB",
"url": "https://docs.stripe.com/checkout/fulfillment#async-payment-methods"
},
{
"type": "WEB",
"url": "https://docs.stripe.com/webhooks#verify-official-libraries"
},
{
"type": "PACKAGE",
"url": "https://github.com/QuantumNous/new-api"
},
{
"type": "WEB",
"url": "https://github.com/QuantumNous/new-api/releases/tag/v0.12.10"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "New API: Stripe Webhook Signature Bypass via Empty Secret Enables Unlimited Quota Fraud"
}
GHSA-XFF9-CGJH-MVPP
Vulnerability from github – Published: 2022-05-24 17:40 – Updated: 2022-05-24 17:40Archer before 6.9 P1 (6.9.0.1) contains an improper access control vulnerability in an API. A remote authenticated malicious administrative user can potentially exploit this vulnerability to gather information about the system, and may use this information in subsequent attacks.
{
"affected": [],
"aliases": [
"CVE-2020-29538"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-01-29T07:15:00Z",
"severity": "MODERATE"
},
"details": "Archer before 6.9 P1 (6.9.0.1) contains an improper access control vulnerability in an API. A remote authenticated malicious administrative user can potentially exploit this vulnerability to gather information about the system, and may use this information in subsequent attacks.",
"id": "GHSA-xff9-cgjh-mvpp",
"modified": "2022-05-24T17:40:35Z",
"published": "2022-05-24T17:40:35Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-29538"
},
{
"type": "WEB",
"url": "https://community.rsa.com/docs/DOC-115223"
},
{
"type": "WEB",
"url": "https://www.rsa.com/en-us/company/vulnerability-response-policy"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-XFH7-PHR7-GR2X
Vulnerability from github – Published: 2026-03-06 18:45 – Updated: 2026-03-06 22:52Impact
The readOnlyMasterKey can be used to create and delete files via the Files API (POST /files/:filename, DELETE /files/:filename). This bypasses the read-only restriction which violates the access scope of the readOnlyMasterKey.
Any Parse Server deployment that uses readOnlyMasterKey and exposes the Files API is affected. An attacker with access to the readOnlyMasterKey can upload arbitrary files or delete existing files.
Patches
The fix adds permission checks to both the file upload and file delete handlers.
Workarounds
There is no workaround other than not using readOnlyMasterKey, or restricting network access to the Files API endpoints.
References
- GitHub security advisory: https://github.com/parse-community/parse-server/security/advisories/GHSA-xfh7-phr7-gr2x
- Fix for Parse Server 9: https://github.com/parse-community/parse-server/releases/tag/9.5.0-alpha.3
- Fix for Parse Server 8: https://github.com/parse-community/parse-server/releases/tag/8.6.5
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "parse-server"
},
"ranges": [
{
"events": [
{
"introduced": "9.0.0"
},
{
"fixed": "9.5.0-alpha.3"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "parse-server"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "8.6.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-30228"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-06T18:45:36Z",
"nvd_published_at": "2026-03-06T21:16:16Z",
"severity": "MODERATE"
},
"details": "### Impact\n\nThe `readOnlyMasterKey` can be used to create and delete files via the Files API (`POST /files/:filename`, `DELETE /files/:filename`). This bypasses the read-only restriction which violates the access scope of the `readOnlyMasterKey`.\n\nAny Parse Server deployment that uses `readOnlyMasterKey` and exposes the Files API is affected. An attacker with access to the `readOnlyMasterKey` can upload arbitrary files or delete existing files.\n\n### Patches\n\nThe fix adds permission checks to both the file upload and file delete handlers.\n\n### Workarounds\n\nThere is no workaround other than not using `readOnlyMasterKey`, or restricting network access to the Files API endpoints.\n\n### References\n \n- GitHub security advisory: https://github.com/parse-community/parse-server/security/advisories/GHSA-xfh7-phr7-gr2x\n- Fix for Parse Server 9: https://github.com/parse-community/parse-server/releases/tag/9.5.0-alpha.3\n- Fix for Parse Server 8: https://github.com/parse-community/parse-server/releases/tag/8.6.5",
"id": "GHSA-xfh7-phr7-gr2x",
"modified": "2026-03-06T22:52:58Z",
"published": "2026-03-06T18:45:36Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/parse-community/parse-server/security/advisories/GHSA-xfh7-phr7-gr2x"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-30228"
},
{
"type": "PACKAGE",
"url": "https://github.com/parse-community/parse-server"
},
{
"type": "WEB",
"url": "https://github.com/parse-community/parse-server/releases/tag/8.6.5"
},
{
"type": "WEB",
"url": "https://github.com/parse-community/parse-server/releases/tag/9.5.0-alpha.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "parse-server\u0027s file creation and deletion bypasses `readOnlyMasterKey` write restriction"
}
GHSA-XFQ3-QJ7J-4565
Vulnerability from github – Published: 2025-12-26 03:30 – Updated: 2025-12-26 19:12Gitea before 1.22.3 mishandles access to a private resource upon receiving an API token with scope limited to public resources.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "code.gitea.io/gitea"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.22.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-68941"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2025-12-26T19:12:54Z",
"nvd_published_at": "2025-12-26T03:15:50Z",
"severity": "MODERATE"
},
"details": "Gitea before 1.22.3 mishandles access to a private resource upon receiving an API token with scope limited to public resources.",
"id": "GHSA-xfq3-qj7j-4565",
"modified": "2025-12-26T19:12:54Z",
"published": "2025-12-26T03:30:15Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-68941"
},
{
"type": "WEB",
"url": "https://github.com/go-gitea/gitea/pull/32218"
},
{
"type": "WEB",
"url": "https://blog.gitea.com/release-of-1.22.3"
},
{
"type": "PACKAGE",
"url": "https://github.com/go-gitea/gitea"
},
{
"type": "WEB",
"url": "https://github.com/go-gitea/gitea/releases/tag/v1.22.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Gitea mishandles access to a private resource upon receiving an API token with scope limited to public resources"
}
Mitigation
- 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
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
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
- 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
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.
No CAPEC attack patterns related to this CWE.