CVE-2026-25150 Overview
A critical prototype pollution vulnerability has been identified in the Qwik JavaScript framework, specifically within the formToObj() function of the @builder.io/qwik-city middleware. This vulnerability allows unauthenticated remote attackers to manipulate Object.prototype by sending specially crafted HTTP POST requests containing malicious form field names using dot notation.
The formToObj() function processes form field names with dot notation (e.g., user.name) to create nested objects but fails to sanitize dangerous property names including __proto__, constructor, and prototype. This oversight enables attackers to inject arbitrary properties into the JavaScript Object prototype, affecting all objects in the application runtime.
Critical Impact
Unauthenticated attackers can achieve privilege escalation, authentication bypass, or denial of service through prototype pollution by sending crafted HTTP POST requests to any Qwik application using the affected middleware.
Affected Products
- Qwik Framework versions prior to 1.19.0
- @builder.io/qwik-city middleware package
- Applications using form parsing functionality in affected versions
Discovery Timeline
- 2026-02-03 - CVE-2026-25150 published to NVD
- 2026-02-04 - Last updated in NVD database
Technical Details for CVE-2026-25150
Vulnerability Analysis
This prototype pollution vulnerability (CWE-1321) exists in the form parsing middleware of the Qwik framework. The vulnerability allows attackers to modify the prototype chain of JavaScript objects without authentication, potentially compromising the entire application's security model.
When a form submission is processed, the formToObj() function iterates through form field names and uses dot notation to create nested object structures. The function did not validate whether the property names being set correspond to protected prototype properties. By submitting form fields with names like __proto__.isAdmin or constructor.prototype.authorized, an attacker can inject properties that will be inherited by all objects created after the pollution occurs.
The consequences of successful exploitation include authentication bypass if the application checks for user properties that can be polluted, privilege escalation by injecting administrative flags, and denial of service through property pollution that breaks application logic.
Root Cause
The root cause lies in the lack of input sanitization for dangerous JavaScript property names within the formToObj() function. The function uses a reduce() operation to build nested objects from dot-separated field names without checking if those names reference prototype chain properties. Specifically, the original implementation allowed form field names containing __proto__, constructor, or prototype to be processed normally, enabling direct manipulation of Object.prototype.
Attack Vector
The attack is network-based and requires no authentication or user interaction. An attacker can exploit this vulnerability by sending an HTTP POST request with form data containing specially crafted field names:
- Attacker identifies a Qwik application using the vulnerable @builder.io/qwik-city middleware
- Attacker crafts a POST request with form fields like __proto__.polluted=true
- The formToObj() function processes the request and pollutes Object.prototype
- All subsequently created objects inherit the polluted properties
- Application logic depending on property existence or truthiness may behave unexpectedly
// Security patch demonstrating the vulnerability fix
// Source: https://github.com/QwikDev/qwik/commit/5f65bae2bc33e6ca0c21e4cfcf9eae05077716f7
+import { describe, it, expect } from 'vitest';
+import { formToObj } from './request-event';
+
+describe('formToObj', () => {
+ describe('Object prototype pollution', () => {
+ it('blocks __proto__ pollution via dotted notation', () => {
+ delete (Object.prototype as any).polluted;
+
+ const fd = new FormData();
+ fd.append('__proto__.polluted', '1');
+
+ formToObj(fd);
+
+ expect(({} as any).polluted).toBeUndefined();
+
+ delete (Object.prototype as any).polluted;
+ });
+
+ it('blocks __proto__[] pollution via array notation', () => {
+ delete (Object.prototype as any).polluted;
+
+ const fd = new FormData();
+ fd.append('__proto__[]', 'x');
+
+ const res = formToObj(fd);
+
+ expect(({} as any).polluted).toBeUndefined();
+ expect(Object.prototype.hasOwnProperty.call(res, '__proto__')).toBe(false);
+
+ delete (Object.prototype as any).polluted;
The patch implements a isDangerousKey() function and creates objects using Object.create(null) to prevent prototype chain pollution:
// Core fix in request-event.ts
// Source: https://github.com/QwikDev/qwik/commit/5f65bae2bc33e6ca0c21e4cfcf9eae05077716f7
return undefined;
};
-const formToObj = (formData: FormData): Record<string, any> => {
+const isDangerousKey = (k: string) => k === '__proto__' || k === 'constructor' || k === 'prototype';
+
+export const formToObj = (formData: FormData): Record<string, any> => {
/**
* Convert FormData to object Handle nested form input using dot notation Handle array input using
* indexed dot notation (name.0, name.0) or bracket notation (name[]), the later is needed for
* multiselects Create values object by form data entries
*/
- const values = [...formData.entries()].reduce<any>((values, [name, value]) => {
- name.split('.').reduce((object: any, key: string, index: number, keys: any) => {
- // Backet notation for arrays, notibly for multi selects
+ const values = Object.create(null);
+
+ for (const [name, value] of formData) {
+ const keys = name.split('.');
+ let hasDangerousKey = false;
+
+ for (let i = 0; i < keys.length; i++) {
+ if (isDangerousKey(keys[i])) {
+ hasDangerousKey = true;
+ break;
+ }
+ }
+
+ if (hasDangerousKey) {
+ continue;
Detection Methods for CVE-2026-25150
Indicators of Compromise
- HTTP POST requests containing form field names with __proto__, constructor, or prototype segments
- Unusual application behavior indicating object property pollution
- Authentication or authorization anomalies where users gain unexpected privileges
- Application crashes or errors related to unexpected object properties
Detection Strategies
- Implement Web Application Firewall (WAF) rules to detect and block requests containing prototype pollution patterns in form data
- Monitor application logs for form submissions with suspicious field names containing __proto__, constructor, or prototype
- Deploy runtime application self-protection (RASP) solutions that can detect prototype pollution attempts
- Use SentinelOne Singularity XDR to correlate network and application layer events for comprehensive threat detection
Monitoring Recommendations
- Enable detailed logging for form processing in Qwik applications to capture suspicious input patterns
- Set up alerts for authentication or authorization changes that occur without corresponding user actions
- Monitor for unexpected properties appearing on JavaScript objects in production environments
- Implement anomaly detection for HTTP request payloads targeting form endpoints
How to Mitigate CVE-2026-25150
Immediate Actions Required
- Upgrade @builder.io/qwik-city to version 1.19.0 or later immediately
- Audit application code for custom form parsing logic that may be similarly vulnerable
- Review application logs for any historical exploitation attempts
- Implement input validation at the WAF layer as defense-in-depth
Patch Information
The vulnerability has been patched in Qwik version 1.19.0. The fix introduces a isDangerousKey() helper function that blocks processing of form fields containing __proto__, constructor, or prototype in their names. Additionally, the fix uses Object.create(null) to create objects without a prototype chain, providing defense-in-depth against prototype pollution.
For detailed patch information, refer to the GitHub Security Advisory GHSA-xqg6-98cw-gxhq and the security patch commit.
Workarounds
- Deploy a WAF rule to block HTTP POST requests containing __proto__, constructor, or prototype in form field names
- Implement server-side input validation to reject form submissions with dangerous property names before they reach the Qwik middleware
- Use reverse proxy filtering to sanitize incoming form data
- Consider temporarily disabling form processing endpoints if patching is not immediately possible
# Example nginx configuration to block prototype pollution attempts
location / {
# Block requests with prototype pollution patterns in body
if ($request_body ~* "__proto__|constructor\.prototype|prototype\.") {
return 403;
}
proxy_pass http://qwik_backend;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

