GHSA-72h8-wp98-7hch: Npm/unleash-server vulnerability

Published Sep 22, 2026
·
Updated

Summary

Multiple authorization vulnerabilities in Unleash admin API, including a critical missing await that completely bypasses a permission check.

Vulnerability 1: Missing await on Permission Check (HIGH)

File: src/lib/features/segment/segment-controller.ts (line 345)

POST /api/admin/segments/strategies has permission: NONE at the route level. The handler performs its own check via this.accessService.hasPermission(), but omits the await keyword. Since hasPermission() is async (returns Promise<boolean>), the variable always receives a truthy Promise object. The if (!hasFeatureStrategyPermission) check never triggers.

typescript // BUG: missing await - hasPermission() returns Promise<boolean> const hasFeatureStrategyPermission = this.accessService.hasPermission( req.user, UPDATEFEATURESTRATEGY, projectId, environmentId, ); if (!hasFeatureStrategyPermission) { // Always false - Promise is truthy! res.status(403).send(); return; }

Impact: Any authenticated user can modify segment assignments on ANY strategy across ALL projects.

Fix: Add await: const hasFeatureStrategyPermission = await this.accessService.hasPermission(...)

Vulnerability 2: Cross-Project Variant Read (MEDIUM)

File: src/lib/routes/admin-api/project/variants.ts (line 213-223)

GET /api/admin/projects/:projectId/features/:featureName/environments/:environment/variants completely ignores projectId. getVariantsOnEnv() only uses featureName and environment.

Impact: Any authenticated user can read variant configs (names, weights, payloads) from any project.

Vulnerability 3: Cross-Project Strategy Read (MEDIUM)

File: src/lib/features/feature-toggle/feature-toggle-controller.ts (line 1107-1116)

GET .../strategies/:strategyId ignores all params except strategyId. Any authenticated user can read any strategy's full configuration.

Vulnerability 4: Cross-Project Environment Info Leak (MEDIUM)

File: src/lib/features/feature-toggle/feature-toggle-service.ts (line 1611)

getEnvironmentInfo() doesn't validate feature belongs to project. Compare with getFeature() which calls validateFeatureBelongsToProject().

Vulnerability 5: Cross-Project Tag Modification (LOW)

File: src/lib/features/feature-toggle/feature-toggle-controller.ts (line 576-596)

PUT /:projectId/tags accepts features array in body without validating they belong to projectId.

Affected Software

1 affected componentFixes available
npm/unleash-server<8.0.3
8.0.3

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/unleash-server to a version that resolves this vulnerability.

    Fixed in 8.0.3
  2. Configuration

    Await the asynchronous permission check before evaluating it: const hasFeatureStrategyPermission = await this.accessService.hasPermission(...).

    feature-toggle-controller.ts hasFeatureStrategyPermission = await this.accessService.hasPermission(...)
  3. Configuration

    Validate that the requested strategy, feature, environment information, variant configuration, and tag-targeted features belong to the specified project before allowing reads or modifications.

    Unleash admin API project-scoped endpoints project ownership validation = enabled

Event History

Sep 22, 2026
Advisory Published
via GitHub·08:36 PM
Data Sourced
via GitHub·08:36 PM
DescriptionWeaknessAffected Software

Frequently Asked Questions

1

Who can exploit the missing permission check?

Any authenticated user can exploit it. The vulnerable endpoint allows that user to modify segment assignments on any strategy across all projects.

2

What authorization is required to reach the affected endpoint?

No route-level permission is required because POST /api/admin/segments/strategies is configured with permission: NONE. Its intended handler-level permission check is bypassed because the asynchronous check is not awaited.

3

How can teams determine whether this specific issue is present in their code?

Inspect src/lib/features/segment/segment-controller.ts around line 345 for the POST /api/admin/segments/strategies handler. It is affected if hasPermission() is called without await and its returned Promise is used in the authorization conditional.

4

What is the direct remediation for the described permission bypass?

Await the accessService.hasPermission() call before evaluating its result. This makes a false permission result trigger the intended 403 response.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203