The JSON Security Landscape in 2025
As JSON has become the backbone of modern web applications, it has also become a prime target for attackers. In 2024 alone, security researchers reported over 500 JSON-related vulnerabilities across popular frameworks and libraries. This comprehensive guide will teach you everything you need to know to secure your JSON data and APIs.
⚠️ Warning
⚠️ The Reality of JSON Security Risks
Why JSON is Targeted
- Ubiquity - JSON is everywhere, making it a high-value target for attackers
- Trusted Data - Many applications trust JSON data without proper validation
- eval() Legacy - Historical use of eval() for parsing created vulnerabilities
- Complex Parsers - Different parsers have different behaviors and edge cases
- API Growth - Rapid API development often bypasses security reviews
JSON Injection Attacks: Complete Guide
1. JSON Injection (aka JSON Hijacking)
Attackers inject malicious JSON payloads that can manipulate application logic, steal data, or execute unauthorized actions.
🔴 Vulnerable Code Example
// User input: { "name": "John", "role": "user" }
const userInput = req.body;
db.users.updateOne(
{ id: userId },
{ $set: userInput }
);
// Attacker sends: { "name": "John",
// "role": "admin",
// "$inc": { "wallet": 1000000 }
// }
// Result: Admin privileges + wallet increased!
✅ Good to Know
✅ Secure Code Example
// Whitelist allowed fields
const allowedUpdates = ['name', 'email', 'profile'];
const sanitizedInput = {};
for (const key of allowedUpdates) {
if (userInput[key] !== undefined) {
sanitizedInput[key] = sanitizeValue(userInput[key]);
}
}
db.users.updateOne(
{ id: userId },
{ $set: sanitizedInput }
);
2. NoSQL Injection (MongoDB, CouchDB, etc.)
NoSQL databases are vulnerable to injection attacks when JSON input is directly used in queries without sanitization.
🔴 Vulnerable
// Attacker sends
{ "username": "admin",
"password": { "$ne": null } }
db.users.find({
username: req.body.username,
password: req.body.password
});
// This returns the admin user
// without password verification!
✅ Good to Know
✅ Secure
// Never trust user input in queries
db.users.findOne({
username: req.body.username,
password: hashPassword(req.body.password)
});
🛡️ Prevention Strategies
- Input validation - Always validate and sanitize all JSON input before processing
- Whitelist approach - Define allowed fields and reject anything else
- Parameterized queries - Use parameterized database queries instead of direct JSON insertion
- JSON Schema validation - Validate incoming data against a strict schema
- Escape output - Escape JSON output when embedding in HTML or other contexts
Preventing XSS in JSON Responses
When JSON responses contain user-generated content and are embedded in HTML pages, XSS (Cross-Site Scripting) attacks become possible.
🚨 XSS Attack Example
// User saves this as username
"
"
// API returns JSON
{"username": "
"}
// If rendered directly in HTML
Hello,
// This executes the XSS payload!
✅ Good to Know
✅ Prevention Methods
- Use .textContent instead of .innerHTML
- Content Security Policy (CSP) - Restrict script execution
- Sanitize on server - Use libraries like DOMPurify
- Escape JSON output - Replace < > & etc.
- Set secure headers - X-Content-Type-Options: nosniff
Safe JSON Response Headers
// Set these headers for all JSON responses
X-Content-Type-Options: nosniff
Content-Type: application/json; charset=utf-8
Content-Security-Policy: default-src 'none'
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
CSRF Protection for JSON APIs
JSON APIs are vulnerable to Cross-Site Request Forgery (CSRF) attacks, especially when using cookies for authentication.
How CSRF Attacks JSON APIs
// Malicious website can make POST requests to your API
// Browser automatically includes your cookies!
Defense Strategies
CSRF Tokens
Include a unique token in JSON requests that's validated server-side
SameSite Cookies
Set SameSite=Strict or SameSite=Lax on authentication cookies
Custom Headers
Require X-Requested-With or other custom headers
// Secure cookie configuration
Set-Cookie: sessionId=abc123; SameSite=Strict; Secure; HttpOnly
// Or require custom header (Angular/React/Vue can add automatically)
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
Secure JSON Parsing: Avoiding Common Pitfalls
⚠️ Warning
🚨 NEVER use eval() for JSON parsing!
// DANGEROUS - NEVER DO THIS
const data = eval('(' + jsonString + ')'); // Code injection risk!
// SAFE - Always use JSON.parse()
const data = JSON.parse(jsonString);
JSON.parse Security Features & Limitations
// JSON.parse is safe from code injection, but has other risks
// reviver function for additional validation
const data = JSON.parse(jsonString, (key, value) => {
// Validate and sanitize values during parsing
if (key === 'email' && typeof value === 'string') {
if (!isValidEmail(value)) {
throw new Error('Invalid email format');
}
return sanitizeEmail(value);
}
return value;
});
// Size limits - always implement!
if (jsonString.length > MAX_SIZE) {
throw new Error('JSON payload too large');
}
const data = JSON.parse(jsonString);
DoS Attacks via JSON
JSON can be used to launch Denial of Service (DoS) attacks through various techniques:
Deeply Nested Objects
Causes stack overflow in parsers. Limit nesting depth to 5-10 levels.
{"a":{"b":{"c":{"d":{"e":{"f":{"g":{"h":{"i":{"j":"crash"}}}}}}}}}}
Hash Collision Attacks
Large objects with colliding hash keys can cause hash table blowup in some parsers.
Large Arrays & Strings
Very long strings or huge arrays consume excessive memory. Implement size limits.
DoS Prevention Code
// Node.js example with express-rate-limit and payload limits
import rateLimit from 'express-rate-limit';
// Limit payload size
app.use(express.json({ limit: '1mb' }));
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per window
message: 'Too many requests from this IP'
});
app.use('/api/', limiter);
// Custom JSON parser with depth limits
function safeJsonParse(str, maxDepth = 10) {
let depth = 0;
return JSON.parse(str, (key, value) => {
if (typeof value === 'object' && value !== null) {
depth++;
if (depth > maxDepth) {
throw new Error('Maximum nesting depth exceeded');
}
}
return value;
});
}
JSON Security Checklist
✅ Input Validation
- Validate all JSON input against a schema
- Whitelist allowed fields, reject everything else
- Validate data types and ranges
- Sanitize user-generated content
- Check for injection patterns
✅ Output Encoding
- Escape JSON when embedding in HTML
- Set proper Content-Type headers
- Use JSON.parse() not eval()
- Consider CSP headers
- XSS-proof your JSON responses
✅ Authentication & Authorization
- Use strong authentication (JWT, OAuth2)
- Implement proper authorization checks
- Never trust client-side only checks
- Secure session management
- Implement rate limiting
✅ CSRF & XSS Protection
- Use CSRF tokens or SameSite cookies
- Set X-Frame-Options: DENY
- Set X-Content-Type-Options: nosniff
- Implement Content Security Policy
- Validate origin/referer headers
✅ DoS Protection
- Limit JSON payload size (1MB-10MB)
- Limit nesting depth (max 10)
- Implement rate limiting
- Use streaming parsers for large files
- Set request timeouts
✅ Monitoring & Logging
- Log validation failures
- Monitor for injection attempts
- Alert on rate limit violations
- Track schema validation errors
- Regular security audits
Secure Your JSON Data Today
Use our free JSON formatter with built-in validation to ensure your data is secure and properly formatted.
🔒 Secure Your JSON →