CVE-2026-1774: Verified Repro With Script Download
CVE-2026-1774: CASL Ability: Prototype Pollution via Condition Handling
CVE-2026-1774 is verified against @casl/ability · npm. Affected versions: >= 2.4.0, <= 6.7.4. Fixed in 6.7.5. Vulnerability class: Prototype Pollution. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00097.
What Is CVE-2026-1774?
CVE-2026-1774 is a critical (CVSS 9.8 per the advisory) prototype pollution vulnerability (CWE-1321) in @casl/ability, versions 2.4.0 through 6.7.4, reachable through the rulesToFields function when it processes user-controlled ability rule conditions. Pruva reproduced it (reproduction REPRO-2026-00097).
CVE-2026-1774 Severity & CVSS Score
CVE-2026-1774 is rated critical severity, with a CVSS base score of 9.8 out of 10.
Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.
Affected @casl/ability Versions
@casl/ability · npm versions >= 2.4.0, <= 6.7.4 are affected.
How to Reproduce CVE-2026-1774
pruva-verify REPRO-2026-00097 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00097/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-1774
Reproduced by Pruva's autonomous agents — 78 tool calls over 6 min. Full root-cause analysis and the complete transcript are below.
How the agent worked
Root Cause and Exploit Chain for CVE-2026-1774
Summary
The CASL Ability library (versions 2.4.0 through 6.7.4) contains a prototype pollution vulnerability in the setByPath utility function. When the rulesToFields function processes ability rules containing malicious condition keys like __proto__.polluted, it passes these paths to setByPath, which unsafely traverses and modifies object properties without validating against dangerous property names. This allows attackers to pollute Object.prototype, potentially leading to privilege escalation, denial of service, or unauthorized access across the entire application.
Impact
- Package:
@casl/ability(npm) - Affected Versions: >= 2.4.0, <= 6.7.4
- Fixed in Version: 6.7.5
- CVE: CVE-2026-1774
- CVSS: 9.8 (CRITICAL)
- CVSS Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - CWE: CWE-1321 (Prototype Pollution)
Risk Level and Consequences
This is a critical severity vulnerability with the following potential impacts:
- Confidentiality: High - Attackers may bypass authorization checks by manipulating object properties
- Integrity: High - Modified prototypes can alter application behavior globally
- Availability: High - Polluted prototypes can cause application crashes or infinite loops
The vulnerability affects any application using the rulesToFields function from @casl/ability/extra with user-controlled rule conditions.
Root Cause
The vulnerability exists in the setByPath function in packages/casl-ability/src/utils.ts. This function sets nested properties on an object using a dot-notation path string. Prior to the fix, setByPath did not validate the property names within the path, allowing dangerous properties like __proto__, constructor, and prototype to be used in paths.
Vulnerable Code Pattern
// Vulnerable version (before 6.7.5)
export function setByPath(object: AnyObject, path: string, value: unknown): void {
let ref = object;
let lastKey = path;
if (path.indexOf('.') !== -1) {
const keys = path.split('.');
lastKey = keys.pop()!;
ref = keys.reduce((res, prop) => {
// NO VALIDATION - dangerous properties allowed
res[prop] = res[prop] || {};
return res[prop] as AnyObject;
}, object);
}
ref[lastKey] = value; // Direct assignment without validation
}
Attack Vector
The rulesToFields function is part of the public API and is commonly used to extract rule conditions into field objects. When an attacker can control the conditions of rules passed to rulesToFields, they can craft a malicious path:
can('read', 'Post', { '__proto__.__pollutedValue__': 1 })
When rulesToFields processes this rule, it calls:
setByPath(fields, '__proto__.__pollutedValue__', 1)
This traverses fields.__proto__ (which is Object.prototype) and sets __pollutedValue__ = 1, polluting the global object prototype.
Fix
The patch introduces a FORBIDDEN_PROPERTIES set and validates each property in the path:
const FORBIDDEN_PROPERTIES = new Set(['__proto__', 'constructor', 'prototype']);
export function setByPath(object: AnyObject, path: string, value: unknown): void {
// ... path splitting ...
ref = keys.reduce((res, prop) => {
if (FORBIDDEN_PROPERTIES.has(prop)) return res; // BLOCKED
res[prop] = res[prop] || {};
return res[prop] as AnyObject;
}, object);
if (!FORBIDDEN_PROPERTIES.has(lastKey)) {
ref[lastKey] = value; // Only set if not forbidden
}
}
Fix Commit: https://github.com/stalniy/casl/commit/39da920ec1dfadf3655e28bd0389e960ac6871f4
Reproduction Steps
The reproduction script is located at repro/reproduction_steps.sh.
What the Script Does
- Installs vulnerable version (6.7.3): Sets up a test environment with the vulnerable
@casl/abilitypackage - Tests prototype pollution: Creates an ability with a malicious condition containing
__proto__.__pollutedValue__and callsrulesToFields. Verifies thatObject.prototypeis polluted. - Installs patched version (6.7.5): Upgrades to the fixed version
- Verifies the fix: Repeats the test and confirms that
Object.prototypeis NOT polluted in the fixed version
Expected Evidence
The script produces the following evidence in logs/:
npm_install_vuln.log- Installation of vulnerable versiontest_vulnerable.log- Demonstrates prototype pollutionnpm_install_fixed.log- Installation of fixed versiontest_fixed.log- Confirms fix works
Key Evidence from Vulnerable Version:
Before test: ({}).__pollutedValue__ = undefined
After rulesToFields: ({}).__pollutedValue__ = 1
Returned fields: {}
[FAIL] Prototype pollution confirmed! Object.prototype was polluted.
Key Evidence from Fixed Version:
Before test: ({}).__pollutedValue__ = undefined
After rulesToFields: ({}).__pollutedValue__ = undefined
Returned fields: {"__pollutedValue__":1}
[PASS] Fix confirmed! Object.prototype was NOT polluted.
Note: In the fixed version, the value is stored in the returned fields object (as expected) but does NOT pollute the global Object.prototype.
Evidence
All evidence is captured in the logs/ directory:
/root/.pruva/runs/ghsa-x9vf-53q3-cvx6_20260219-193039/logs/npm_install_vuln.log/root/.pruva/runs/ghsa-x9vf-53q3-cvx6_20260219-193039/logs/test_vulnerable.log/root/.pruva/runs/ghsa-x9vf-53q3-cvx6_20260219-193039/logs/npm_install_fixed.log/root/.pruva/runs/ghsa-x9vf-53q3-cvx6_20260219-193039/logs/test_fixed.log
Environment Details
- Node.js: Available via npm
- Tested Versions:
- Vulnerable: 6.7.3 (also affected 2.4.0 through 6.7.4)
- Fixed: 6.7.5
- Test Environment: Linux, npm package manager
Recommendations / Next Steps
Immediate Actions
Upgrade: Update
@casl/abilityto version 6.7.5 or later immediatelynpm install @casl/ability@^6.7.5Audit: Check if your application uses
rulesToFieldswith user-controlled rule conditionsInput Validation: Until patched, sanitize any user input that might be used in ability rule conditions
Testing Recommendations
- Run
npm auditto identify vulnerable dependencies - Review code that constructs ability rules from user input
- Add regression tests using the reproduction approach in this report
- Monitor for suspicious rule conditions containing
__proto__,constructor, orprototypekeys
Long-term Prevention
- Implement automated security scanning in CI/CD pipelines
- Use lockfiles and audit checks in pre-commit hooks
- Subscribe to security advisories for @casl/ability
Additional Notes
Idempotency Confirmation
The reproduction script was executed twice consecutively with identical results:
- Run 1: Exit code 0 (vulnerability confirmed)
- Run 2: Exit code 0 (vulnerability confirmed)
Both runs successfully demonstrated:
- Vulnerable version (6.7.3) allows prototype pollution
- Fixed version (6.7.5) prevents prototype pollution
Edge Cases and Limitations
- The vulnerability requires the use of
rulesToFieldsfunction with user-controlled conditions - Applications that only use basic ability checks without
rulesToFieldsmay not be directly exploitable - The fix properly handles both dot-notation paths (
__proto__.polluted) and direct property assignments - The fix also protects against
constructor.prototypeattack variants
CVE-2026-1774 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
mkdir -p /root/.pruva/runs/ghsa-x9vf-53q3-cvx6_20260219-193039/repro/logs && cd /root/.pruva/runs/ghsa-x9vf-53q3-cvx6_20260219-193039/repro && git clone --depth 1 https://github.com/stalniy/casl.gitCloning into 'casl'...
Artifacts and Evidence for CVE-2026-1774
Scripts, logs, diffs, and output captured during the reproduction.
No artifacts available
How to Fix CVE-2026-1774
Upgrade @casl/ability · npm to 6.7.5 or later.
FAQ: CVE-2026-1774
How does the CVE-2026-1774 exploit work?
Which versions of @casl/ability are affected by CVE-2026-1774, and where is it fixed?
How severe is CVE-2026-1774?
How can I reproduce CVE-2026-1774?
References for CVE-2026-1774
Authoritative sources for CVE-2026-1774 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.