Human
Machine
REPRO-2026-00097 CRITICAL Prototype Pollution
Verified
CASL Ability: Prototype Pollution via Condition Handling
@casl/ability (npm) Feb 19, 2026
What's the vulnerability?
CASL Ability, versions 2.4.0 through 6.7.4, contains a prototype pollution vulnerability.
Root Cause Analysis
# Root Cause Analysis: GHSA-x9vf-53q3-cvx6
## 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
```typescript
// 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:
```javascript
can('read', 'Post', { '__proto__.__pollutedValue__': 1 })
```
When `rulesToFields` processes this rule, it calls:
```javascript
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:
```typescript
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
1. **Installs vulnerable version (6.7.3)**: Sets up a test environment with the vulnerable `@casl/ability` package
2. **Tests prototype pollution**: Creates an ability with a malicious condition containing `__proto__.__pollutedValue__` and calls `rulesToFields`. Verifies that `Object.prototype` is polluted.
3. **Installs patched version (6.7.5)**: Upgrades to the fixed version
4. **Verifies the fix**: Repeats the test and confirms that `Object.prototype` is NOT polluted in the fixed version
### Expected Evidence
The script produces the following evidence in `logs/`:
- `npm_install_vuln.log` - Installation of vulnerable version
- `test_vulnerable.log` - Demonstrates prototype pollution
- `npm_install_fixed.log` - Installation of fixed version
- `test_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
1. **Upgrade**: Update `@casl/ability` to version 6.7.5 or later immediately
```bash
npm install @casl/ability@^6.7.5
```
2. **Audit**: Check if your application uses `rulesToFields` with user-controlled rule conditions
3. **Input Validation**: Until patched, sanitize any user input that might be used in ability rule conditions
### Testing Recommendations
1. Run `npm audit` to identify vulnerable dependencies
2. Review code that constructs ability rules from user input
3. Add regression tests using the reproduction approach in this report
4. Monitor for suspicious rule conditions containing `__proto__`, `constructor`, or `prototype` keys
### Long-term Prevention
1. Implement automated security scanning in CI/CD pipelines
2. Use lockfiles and audit checks in pre-commit hooks
3. 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:
1. Vulnerable version (6.7.3) allows prototype pollution
2. Fixed version (6.7.5) prevents prototype pollution
### Edge Cases and Limitations
- The vulnerability requires the use of `rulesToFields` function with user-controlled conditions
- Applications that only use basic ability checks without `rulesToFields` may not be directly exploitable
- The fix properly handles both dot-notation paths (`__proto__.polluted`) and direct property assignments
- The fix also protects against `constructor.prototype` attack variants
One Command
Verify with pruva-verify
Run the Pruva CLI to automatically fetch and execute the reproduction script.
pruva-verify REPRO-2026-00097 or
pruva-verify GHSA-x9vf-53q3-cvx6 or
pruva-verify CVE-2026-1774 Install:
curl -fsSL https://pruva.dev/install.sh | sh Or Run Manually
1
Download the script
curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00097/artifacts/reproduction_steps.sh 2
Make executable
chmod +x reproduction_steps.sh 3
Run the script
./reproduction_steps.sh Run in a VM, container, or disposable environment. This exploits a real vulnerability.
How Pruva Reproduced This
Watch the AI agent's step-by-step process.
Loading session...
Artifacts
No artifacts available