CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-68M9-983M-F3V5
7.5

GHSA-68M9-983M-F3V5: Credential Exposure in OpenFGA Playground Endpoint

Alon Barad
Alon Barad
Software Engineer

Apr 9, 2026·6 min read·1 visit

PoC Available

Executive Summary (TL;DR)

OpenFGA leaks the preshared authentication key in the `/playground` HTML response. Unauthenticated attackers can extract this key to gain full API access. Administrators must upgrade to v1.14.0 or disable the playground.

OpenFGA versions 1.13.1 and prior are vulnerable to sensitive information disclosure when configured with preshared-key authentication and the built-in playground enabled. The server inadvertently embeds the preshared API key into the HTML response of the `/playground` endpoint, allowing unauthenticated attackers to extract the credential and gain administrative access to the OpenFGA API.

Vulnerability Overview

OpenFGA is an open-source, high-performance authorization and permission engine inspired by Google's Zanzibar paper. It allows developers to model fine-grained access control using relationship-based access control (ReBAC). To assist developers in building and testing these authorization models, OpenFGA includes a built-in web-based UI known as the playground, typically served at the /playground endpoint.

The engine supports multiple authentication methods to secure its API endpoints, including OIDC and preshared keys. When configured to use preshared-key authentication (authentication.method: preshared), clients must provide a static API key in the Authorization header to interact with the service. This key acts as the primary defense mechanism against unauthorized access to the authorization data.

The vulnerability, identified as GHSA-68M9-983M-F3V5, manifests when the server is run with both preshared-key authentication and the playground enabled. The server logic responsible for rendering the playground inadvertently leaks the preshared key directly into the client-facing HTML response. An unauthenticated attacker with network access to the playground can extract this credential, entirely bypassing the intended authentication boundary.

Root Cause Analysis

The root cause of this vulnerability lies in the server-side rendering pipeline used to serve the playground application. Modern web applications often require configuration data to be passed from the backend server to the frontend client during initial loading. This process, commonly known as state hydration or configuration injection, involves serializing server-side configuration objects into the initial HTML document.

In vulnerable versions of OpenFGA, the server-side logic constructs a configuration struct to pass to the playground's frontend template. This struct is designed to inform the client-side application about the server's environment, active endpoints, and authentication requirements. However, the logic fails to explicitly filter or sanitize the configuration object before serialization.

Consequently, the raw preshared API key (preshared-key), which is loaded into the server's global configuration state at startup, is included in the data structure passed to the templating engine. The templating engine subsequently writes this sensitive value into the HTML response, typically embedding it within a <script> tag or assigning it to a global JavaScript variable.

This behavior violates the principle of least privilege for data exposure, resulting in CWE-200 (Exposure of Sensitive Information to an Unauthorized Actor). The application incorrectly assumes that the configuration object being serialized contains only public or client-safe metadata.

Code Analysis and Data Flow

The vulnerability stems from passing unfiltered configuration data directly into Go's HTML template rendering function. When the /playground HTTP handler processes an incoming GET request, it gathers the necessary server settings to render the UI.

Prior to the patch, the HTTP handler simply passed a broader configuration object that retained the preshared-key field. Because Go's JSON marshaler processes all exported fields of a struct unless explicitly ignored via struct tags (json:"-"), the sensitive key was serialized into the payload destined for the client browser.

The remediation strategy implemented in version 1.14.0 involves strict filtering of the configuration object before it reaches the templating engine. The fix ensures that a dedicated, sanitized struct—containing only the specific fields required by the frontend—is constructed and passed to the template.

By decoupling the server's internal configuration state from the data transfer object (DTO) used for client rendering, the developers eliminate the risk of inadvertent credential leakage. This explicit field mapping ensures that even if new sensitive configuration options are added to the server in the future, they will not automatically propagate to the playground UI.

Exploitation Methodology

Exploiting this vulnerability requires zero authentication and only basic HTTP interaction capabilities. The attacker's primary requirement is network line-of-sight to the vulnerable OpenFGA server's /playground endpoint. The playground is often exposed on port 8080 by default, alongside the primary API endpoints.

The attack begins with a standard HTTP GET request to the /playground route. Because the playground is intended to be the entry point where developers input credentials or construct queries, the endpoint itself is inherently unauthenticated.

curl -s http://openfga.example.com:8080/playground | grep -i "preshared"

Upon receiving the HTML response, the attacker inspects the page source. The embedded preshared key is typically located within a JSON configuration object nested inside a <script> block. The attacker extracts this cleartext string.

Once the key is acquired, the attacker possesses the necessary material to authenticate against the core OpenFGA API. They can format the extracted value into a standard HTTP Authorization header (Authorization: Bearer <extracted_key>). This token grants them the same privileges as the legitimate administrator or service account that was intended to use the preshared key.

Impact Assessment

The security impact of a compromised OpenFGA preshared key is highly severe. OpenFGA acts as the central source of truth for authorization decisions within an organization's architecture. Compromising the authentication layer of the OpenFGA API grants the attacker full administrative control over the authorization state.

With administrative access, an attacker can invoke the Write endpoint to arbitrarily manipulate relationship tuples. This allows them to grant themselves or other compromised accounts elevated permissions in downstream systems that rely on OpenFGA for access control. For example, the attacker could insert a tuple asserting that their user account is an owner of a sensitive target resource.

Furthermore, the attacker gains read access to all existing authorization models and tuple data. This exposes the entire permission graph of the dependent applications, potentially revealing sensitive organizational structures, resource identifiers, and user roles. The attacker can also modify or delete the authorization models entirely, leading to a severe denial-of-service condition for any application relying on the engine to enforce access policies.

Remediation and Mitigation

The primary and most robust remediation for this vulnerability is to upgrade the OpenFGA server to version v1.14.0 or later. The patched version corrects the server-side rendering logic to ensure that sensitive configuration parameters, including the preshared key, are stripped before the playground HTML is generated.

If an immediate upgrade is not operationally feasible, administrators must disable the playground endpoint. This can be achieved by updating the OpenFGA configuration file to set playground.enabled: false. Alternatively, operators can pass the --playground-enabled=false command-line flag when starting the OpenFGA binary. Disabling the playground completely neutralizes the attack vector without impacting the core authorization API functionality.

As a critical post-incident mitigation step, any preshared keys used on vulnerable instances where the playground was accessible to untrusted networks must be considered compromised. Administrators must generate new cryptographic keys, update the OpenFGA configuration, and rotate the credentials in all dependent client applications. Finally, it is an architectural best practice to never expose the playground interface in production environments, regardless of the OpenFGA version or authentication method in use.

Official Patches

OpenFGARelease notes and patch for OpenFGA v1.14.0

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Affected Systems

OpenFGA Server

Affected Versions Detail

Product
Affected Versions
Fixed Version
OpenFGA
OpenFGA
<= 1.13.11.14.0
AttributeDetail
CWE IDCWE-200
Attack VectorNetwork
AuthenticationNone Required
CVSS Score7.5
ImpactCredential Exposure / API Compromise
Exploit StatusProof of Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1552.005Unsecured Credentials: Cloud Instance Metadata API
Credential Access
T1190Exploit Public-Facing Application
Initial Access
CWE-200
Exposure of Sensitive Information to an Unauthorized Actor

The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.

Vulnerability Timeline

Fix Released in OpenFGA v1.14.0
2024-07-01

References & Sources

  • [1]GitHub Advisory: GHSA-68M9-983M-F3V5
  • [2]OpenFGA Repository Security Advisory
  • [3]OpenFGA Release Notes v1.14.0
  • [4]OpenFGA Configuration Documentation

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.