CVE-2026-27167
Gradio's mocked OAuth leaks the server's Hugging Face access token.
- CVSS 5.9
- CWE-522
- Authentication, Authorization, and Session Management
- Remote
Gradio is an open-source Python package designed for quick prototyping. Starting in version 4.16.0 and prior to version 6.6.0, Gradio applications running outside of Hugging Face Spaces automatically enable "mocked" OAuth routes when OAuth components (e.g. `gr.LoginButton`) are used. When a user visits `/login/huggingface`, the server retrieves its own Hugging Face access token via `huggingface_hub.get_token()` and stores it in the visitor's session cookie. If the application is network-accessible, any remote attacker can trigger this flow to steal the server owner's HF token. The session cookie is signed with a hardcoded secret derived from the string `"-v4"`, making the payload trivially decodable. Version 6.6.0 fixes the issue.
- CWE
- CWE-522
- CVSS base score
- 5.9
- Published
- 2026-02-27
- OWASP
- A07 Identification and Authentication Failures
- Orthogonal defect classification
- Checking
- Code defect classification
- Incorrect Algorithm
- Category
- Authentication, Authorization, and Session Management
- Subcategory
- Insecure Handling of Sensitive Data
- Accessibility scope
- Remote
- Impact
- Information Disclosure
- Affected component
- Gradio
- Fixed by upgrading
- Yes
Solution
Upgrade Gradio to version 6.6.0 or later.
Vulnerable code sample
import gradio as gr
# This code requires a vulnerable version of Gradio (e.g., 4.16.0 <= version < 6.6.0)
# and for the server environment to be logged into the Hugging Face Hub.
with gr.Blocks() as demo:
gr.Markdown("A simple Gradio application with an OAuth component.")
gr.LoginButton()
demo.launch()Patched code sample
# This code is a simplified representation of the fix for CVE-2024-27167,
# based on the changes made in the Gradio source code (e.g., in gradio/routes.py).
# The vulnerability was that a "mocked" OAuth flow, intended for local development,
# was enabled by default on self-hosted applications. This flow exposed the
# server's Hugging Face token to any remote user.
# The fix introduces a new parameter, `enable_mocked_oauth`, which defaults
# to False. This ensures the vulnerable code path is not accessible unless
# a developer explicitly opts in for local testing purposes.
from typing import Optional
from fastapi import Request, Response
from huggingface_hub import utils as hf_hub_utils
# A simplified representation of the Gradio App class structure
class App:
def __init__(
self,
space_id: Optional[str] = None,
# THE FIX: A new parameter `enable_mocked_oauth` is introduced, defaulting to `False`.
# This disables the vulnerable mocked OAuth flow by default for self-hosted apps.
enable_mocked_oauth: bool = False,
# ... other parameters
):
self.space_id = space_id
self.enable_mocked_oauth = enable_mocked_oauth
# ... other initializations
# In the original code, the logic to add routes is here.
# The fix ensures these routes are only added if running on Hugging Face Spaces
# (self.space_id is not None) OR if the developer explicitly enables the mock flow.
if self.enable_mocked_oauth or self.space_id:
# In a real app, this would add the route:
# self.add_api_route("/login/huggingface", self.login_huggingface, methods=["GET"])
pass
async def login_huggingface(self, request: Request) -> Response:
"""
This method handles the Hugging Face login flow.
The fix is demonstrated in the `if not self.space_id:` block.
"""
# If running on a Hugging Face Space, the real (secure) OAuth flow is used.
# This part of the logic was not the source of the vulnerability.
if self.space_id:
# ... code for the real OAuth flow on Hugging Face Spaces ...
return Response("Redirecting to real Hugging Face OAuth...", status_code=302)
# This block handles the "mocked" login for self-hosted apps.
# This is where the vulnerability existed and was fixed.
if not self.space_id:
# THE FIX: This condition now checks the `enable_mocked_oauth` flag.
# If it's False (the default), it returns a 404 Not Found error,
# preventing access to the vulnerable logic.
if not self.enable_mocked_oauth:
return Response(
content="Mocked OAuth is disabled. Set `enable_mocked_oauth=True` in `gr.Blocks()` to enable.",
status_code=404,
)
# This vulnerable code block is now only reachable if a developer
# has explicitly set `enable_mocked_oauth=True` for local testing.
#
# Previously, this block would execute unconditionally for any
# self-hosted Gradio app using an OAuth component.
try:
# Step that caused the vulnerability: getting the SERVER's token.
token = hf_hub_utils.get_token()
if token is None:
return Response("Server not logged in to Hugging Face Hub", status_code=500)
except hf_hub_utils.HfHubLoginError:
return Response("Server not logged in to Hugging Face Hub", status_code=500)
# Step that caused the vulnerability: setting the server's token
# in the VISITOR's session cookie.
response = Response(status_code=302, headers={"Location": "/"})
response.set_cookie(key="access-token-unsecure", value=token)
return response
return Response("This code path should not be reached.", status_code=500)Cite this entry
@misc{vaitp:cve202627167,
title = {{Gradio's mocked OAuth leaks the server's Hugging Face access token.}},
author = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
year = {2026},
note = {VAITP Python Vulnerability Dataset, entry CVE-2026-27167},
howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-27167/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.
The supreme art of war is to subdue the enemy without fighting.
Sun Tzu – “The Art of War”
:: Shaping the future through research and ingenuity ::
