JSON Security: Preventing Common Vulnerabilities
JSON parsing seems straightforward, but careless handling can introduce security vulnerabilities. Learn how to parse JSON safely and protect your applications.
Never use eval() to parse JSON. It executes arbitrary code and is a major security risk.
1. Never Use eval()
Using eval() to parse JSON is extremely dangerous as it will execute any JavaScript code.
// NEVER DO THIS!
const data = eval('(' + jsonString + ')');
// Attacker can inject:
// '(function(){/* malicious code */})()'// Always use JSON.parse() const data = JSON.parse(jsonString); // Throws SyntaxError on invalid JSON // Cannot execute code
2. Prototype Pollution
Malicious JSON can modify object prototypes, affecting all objects in your application.
// Malicious payload
const malicious = '{"__proto__": {"isAdmin": true}}';
// Unsafe merge operation
const config = {};
Object.assign(config, JSON.parse(malicious));
// Now ALL objects have isAdmin: true
const user = {};
console.log(user.isAdmin); // true! Security breach!Prevention
// Use Object.create(null) for config objects
const config = Object.create(null);
// Or filter dangerous keys
function safeParse(jsonString) {
return JSON.parse(jsonString, (key, value) => {
if (key === '__proto__' || key === 'constructor') {
return undefined;
}
return value;
});
}3. JSON Injection in Strings
When embedding user data in JSON strings, always escape properly to prevent injection.
// DON'T build JSON strings manually
const json = '{"name": "' + userInput + '"}';
// If userInput = '", "isAdmin": true, "x": "'
// Result: {"name": "", "isAdmin": true, "x": ""}
// DO use JSON.stringify()
const data = { name: userInput };
const json = JSON.stringify(data);
// User input is properly escaped4. Denial of Service (DoS)
Large or deeply nested JSON can crash your application or consume excessive resources.
// Set limits on JSON size
const MAX_JSON_SIZE = 1024 * 1024; // 1MB
function parseWithLimit(jsonString) {
if (jsonString.length > MAX_JSON_SIZE) {
throw new Error('JSON exceeds size limit');
}
return JSON.parse(jsonString);
}
// For APIs, use middleware to limit body size
app.use(express.json({ limit: '1mb' }));5. Sensitive Data Exposure
Be careful not to include sensitive data in JSON responses or logs.
// Define a toJSON method to control serialization
class User {
constructor(name, email, password) {
this.name = name;
this.email = email;
this.password = password;
}
toJSON() {
return {
name: this.name,
email: this.email
// password is excluded
};
}
}
const user = new User('John', 'john@example.com', 'secret');
console.log(JSON.stringify(user));
// {"name":"John","email":"john@example.com"}Security Checklist
- Always use
JSON.parse(), nevereval() - Validate and sanitize input before processing
- Set size limits on JSON payloads
- Filter dangerous keys like
__proto__ - Use schema validation for untrusted data
- Implement proper error handling without leaking details
- Audit third-party JSON parsing libraries
Conclusion
JSON security is often overlooked, but following these practices will help protect your applications from common vulnerabilities. Always treat JSON from external sources as potentially malicious and validate accordingly.