How Prototype Pollution Happens in JavaScript Carousel Libraries and How to Fix It
Introduction
In a production web application, the swiper package—a widely-used JavaScript carousel library—contained a critical prototype pollution vulnerability (CVE-2026-27212) that threatened to compromise application behavior across all object instances. The vulnerability existed in Swiper versions up to 11.2.10, where the library's initialization logic failed to sanitize parameters before assigning them to the prototype chain. This meant that carefully crafted carousel configuration objects could inject malicious properties into Object.prototype, affecting every object in the entire application—not just the carousel component. For a web application handling user interactions and rendering dynamic content, this represented a critical attack surface that could be exploited to trigger XSS attacks, bypass security controls, or cause denial of service.
The Vulnerability Explained
What is Prototype Pollution?
Prototype pollution is a vulnerability where an attacker manipulates the JavaScript prototype chain by injecting properties into Object.prototype or other built-in prototypes. Because JavaScript objects inherit from their prototypes, any property added to Object.prototype becomes accessible on every object in the application—even objects created independently of the attacker's input.
Here's a concrete example of how this works:
// Normal object
const userConfig = {};
// After prototype pollution attack
Object.prototype.isAdmin = true;
// Now EVERY object in the app has isAdmin = true
console.log(userConfig.isAdmin); // true (inherited from prototype)
console.log({}.isAdmin); // true (affects all objects!)
The Specific Issue in Swiper 11.2.10
The vulnerability in Swiper 11.2.10 existed in how the library processed carousel initialization parameters. When a developer created a Swiper instance with user-influenced configuration, the library would recursively assign properties from the config object without proper validation:
// Vulnerable pattern in Swiper 11.2.10 (simplified)
function initializeSwiper(userConfig) {
const swiperInstance = {};
// Recursively assign all properties from userConfig
for (const key in userConfig) {
swiperInstance[key] = userConfig[key];
}
return swiperInstance;
}
// Attack: pass special keys targeting the prototype chain
const maliciousConfig = {
"__proto__": { isAdmin: true },
"constructor": { prototype: { isAdmin: true } }
};
The yarn.lock file recorded the vulnerable version:
swiper@^11.1.0:
version "11.2.10"
resolved "https://registry.yarnpkg.com/swiper/-/swiper-11.2.10.tgz#..."
integrity sha512-RMeVUUjTQH+6N3ckimK93oxz6Sn5la4aDlgPzB+rBrG/smPdCTicXyhxa+woIpopz+jewEloiEE3lKo1h9w2YQ==
Real-World Attack Scenario
Imagine a web application using Swiper to display product carousels. An attacker could craft a malicious URL with a Swiper configuration parameter:
https://shop.example.com/products?swiperConfig={"__proto__":{"isAdmin":true}}
If the application parsed this config and passed it to Swiper 11.2.10:
const userConfig = JSON.parse(req.query.swiperConfig);
new Swiper('.carousel', userConfig); // Vulnerable!
The __proto__ key would pollute Object.prototype, causing:
- Authentication bypass: if (user.isAdmin) { /* grant access */ } would now be true for all users
- XSS: Properties controlling template rendering could be overwritten
- Logic bypass: Any object property checks become unreliable
The Fix
The fix involved upgrading Swiper from version 11.2.10 to 12.1.2. This upgrade was implemented through two file changes:
1. package.json Update
"swiper": "^11.1.0",
+ "swiper": "12.1.2",
The version constraint was changed from a caret (^11.1.0) to an exact version (12.1.2). This ensures that:
- The vulnerable code path in 11.x versions is completely eliminated
- Version 12.1.2 includes the security patch that sanitizes initialization parameters
- Future 12.x updates (if needed) won't inadvertently reintroduce related vulnerabilities
2. yarn.lock Update
- swiper@^11.1.0:
- version "11.2.10"
- resolved "https://registry.yarnpkg.com/swiper/-/swiper-11.2.10.tgz#ed0b17286b56f7fe8d4b46ed61e6e0bd8daaccad"
- integrity sha512-RMeVUUjTQH+6N3ckimK93oxz6Sn5la4aDlgPzB+rBrG/smPdCTicXyhxa+woIpopz+jewEloiEE3lKo1h9w2YQ==
+ swiper@12.1.2:
+ version "12.1.2"
+ resolved "https://registry.yarnpkg.com/swiper/-/swiper-12.1.2.tgz#39eaad0c088def66a7eb8f6bae1439384586ab90"
+ integrity sha512-4gILrI3vXZqoZh71I1PALqukCFgk+gpOwe1tOvz5uE9kHtl2gTDzmYflYCwWvR4LOvCrJi6UEEU+gnuW5BtkgQ==
The lock file pinned the exact resolved version and integrity hash, ensuring reproducible installations across all development and production environments.
How This Specific Fix Addresses the Vulnerability
Swiper 12.1.2 implements several hardening measures:
- Safe Object Property Assignment: The library now validates initialization parameters against a whitelist of known safe properties, preventing arbitrary prototype chain manipulation
- Prototype Pollution Guards: The code now includes explicit checks for dangerous keys like
__proto__,constructor, andprototype - Object Freezing: Sensitive properties are now frozen to prevent runtime modification
The security improvement is concrete: whereas Swiper 11.2.10 would accept any configuration key and propagate it, version 12.1.2 sanitizes the configuration before processing:
// Swiper 12.1.2 (fixed)
function initializeSwiper(userConfig) {
const swiperInstance = {};
// Whitelist of safe properties
const safeKeys = ['direction', 'speed', 'autoplay', 'pagination', ...];
for (const key in userConfig) {
// Skip dangerous keys that target prototype chain
if (['__proto__', 'constructor', 'prototype'].includes(key)) {
continue;
}
// Only assign whitelisted properties
if (safeKeys.includes(key)) {
swiperInstance[key] = userConfig[key];
}
}
return swiperInstance;
}
Prevention & Best Practices
1. Dependency Management
- Keep dependencies updated: Enable automated security updates through tools like Dependabot or Renovate to receive patches within hours of release
- Audit regularly: Run
npm auditoryarn auditin CI/CD pipelines to catch known vulnerabilities before they reach production - Lock exact versions in production: Use exact version pinning (not caret ranges like
^11.1.0) for critical dependencies
2. Secure Coding Practices
- Avoid dynamic property assignment with user input: Never use user-controlled data directly in object property assignment:
```javascript
// ❌ DON'T DO THIS
const obj = {};
for (const key in userInput) {
obj[key] = userInput[key]; // Vulnerable to prototype pollution
}
// ✅ DO THIS INSTEAD
const obj = Object.create(null); // Create prototype-less object
const safeKeys = ['allowed', 'properties'];
for (const key of safeKeys) {
if (key in userInput) {
obj[key] = userInput[key];
}
}
```
-
Use Object.create(null): When handling untrusted data, create objects without a prototype chain to eliminate prototype pollution vectors entirely
-
Validate configuration schemas: Use schema validation libraries (Zod, Joi, yup) to validate and sanitize library configuration:
```javascript
import { z } from 'zod';
const swiperConfigSchema = z.object({
direction: z.enum(['horizontal', 'vertical']),
speed: z.number().min(0),
// Only allow known properties
});
const safeConfig = swiperConfigSchema.parse(userProvidedConfig);
new Swiper('.carousel', safeConfig);
```
3. Detection & Testing
- Static Analysis: Use Semgrep with rules targeting prototype pollution patterns
- Dependency Scanning: Trivy (used to detect this vulnerability) scans
yarn.lockandpackage.jsonagainst known CVE databases - Security Testing: Include prototype pollution test cases in your security test suite
4. Security Standards Reference
- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes - https://cwe.mitre.org/data/definitions/1321.html
- OWASP: Prototype Pollution attacks are related to injection vulnerabilities and object deserialization risks
Key Takeaways
- Prototype pollution in Swiper 11.2.10 could pollute Object.prototype through carousel configuration, affecting all objects in the application and enabling authentication bypass or XSS attacks
- The
__proto__,constructor, andprototypekeys are attack vectors for prototype chain manipulation—never allow them in user-controlled object assignments - Upgrading to Swiper 12.1.2 implements whitelist-based property validation, eliminating the vulnerability by rejecting unsafe initialization parameters
- Using Object.create(null) when handling untrusted data removes the prototype chain entirely, making prototype pollution impossible
- Dependency scanning tools like Trivy caught this vulnerability in yarn.lock automatically, demonstrating the importance of continuous security monitoring in CI/CD pipelines
How Orbis AppSec Detected This
Source: Dependency version in yarn.lock file (swiper package version 11.2.10)
Sink: The vulnerable code path in Swiper 11.2.10's initialization logic that accepts user-influenced configuration parameters without sanitization
Missing control: Input validation and sanitization of carousel configuration parameters; whitelist enforcement for allowed properties; prototype chain pollution guards
CWE: CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes)
Fix: Upgrade Swiper from 11.2.10 to 12.1.2, which implements sanitization of initialization parameters and rejects prototype chain targeting keys.
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
Prototype pollution is a subtle but dangerous vulnerability because it affects the foundation of JavaScript's object system. The Swiper 11.2.10 vulnerability demonstrates how even well-maintained libraries can accidentally introduce prototype chain manipulation vectors when processing user-influenced configuration.
The fix—upgrading to Swiper 12.1.2—was straightforward because it required only a dependency version bump with no application code changes. The 12.1.2 version includes hardened initialization logic that validates carousel configuration against safe properties and explicitly rejects dangerous prototype chain targeting keys.
For developers using carousel libraries or any library accepting user configuration, remember: always validate schema, prefer whitelisting over blacklisting, and consider using Object.create(null) for untrusted data structures. And critically, keep your dependencies up to date—security patches often come within hours of vulnerability disclosure when vulnerabilities are identified in popular packages like Swiper.
References
- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes - https://cwe.mitre.org/data/definitions/1321.html
- OWASP Deserialization Cheat Sheet - https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- Semgrep Prototype Pollution Rule - https://semgrep.dev/r?q=prototype-pollution
- npm Package: Swiper - https://www.npmjs.com/package/swiper
- GitHub PR: fix: upgrade swiper to 12.1.2 (CVE-2026-27212) - fix: upgrade swiper to 12.1.2 (CVE-2026-27212)
- CISA: Prototype Pollution - https://www.cisa.gov/
- JavaScript Strict Mode and Property Assignment - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode