Built-in Protection
Rule Engine JS has security features enabled by default:
Prototype Protection
Blocks proto and constructor access
Function Blocking
Functions cannot be accessed via paths
Depth Limits
Prevents infinite recursion attacks
Type Validation
Validates operator arguments
Prototype Pollution
What It Is
Malicious path access that modifies object prototypes.
// ❌ DANGEROUS - Don't allow this
const maliciousPath = '__proto__.isAdmin';
const maliciousData = {
'__proto__': { isAdmin: true }
};
How We Block It
// ✅ BLOCKED automatically
engine.resolvePath(data, '__proto__');
// Returns: undefined (blocked)
engine.resolvePath(data, 'constructor');
// Returns: undefined (blocked)
engine.resolvePath(data, '__proto__.polluted');
// Returns: undefined (blocked)
Configuration
const engine = createRuleEngine({
allowPrototypeAccess: false // Default: false (KEEP IT!)
});
Never set allowPrototypeAccess: true in production! It opens critical security vulnerabilities.
Always validate user input before using in rules.
Bad vs Good
❌ Bad - No Validation
✅ Good - Validated
// Direct user input (DANGEROUS!)
app.post('/check', (req, res) => {
const rule = req.body.rule; // Unvalidated!
const result = engine.evaluateExpr(rule, data);
res.json(result);
});
Whitelist Operators
Only allow specific operators in user-defined rules.
const SAFE_OPERATORS = [
'eq', 'neq', 'gt', 'gte', 'lt', 'lte',
'and', 'or', 'not',
'in', 'notIn',
'contains', 'startsWith', 'endsWith'
];
function validateRule(rule) {
const operators = extractOperators(rule);
return operators.every(op => SAFE_OPERATORS.includes(op));
}
function extractOperators(rule) {
if (typeof rule !== 'object') return [];
const ops = Object.keys(rule);
const nested = Object.values(rule)
.filter(v => typeof v === 'object')
.flatMap(extractOperators);
return [...ops, ...nested];
}
// Usage
if (!validateRule(userRule)) {
throw new Error('Rule contains disallowed operators');
}
Whitelist Paths
Restrict which data paths can be accessed.
const ALLOWED_PATHS = [
'user.name',
'user.age',
'user.email',
'order.total',
'order.status'
];
function validatePath(path) {
return ALLOWED_PATHS.includes(path);
}
function validateRulePaths(rule) {
const paths = extractPaths(rule);
return paths.every(validatePath);
}
function extractPaths(rule) {
if (Array.isArray(rule)) {
return rule
.filter(item => typeof item === 'string')
.filter(item => item.includes('.'));
}
return Object.values(rule).flatMap(extractPaths);
}
Rate Limiting
Prevent DoS via excessive evaluations.
const rateLimit = require('express-rate-limit');
const ruleLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100, // 100 requests per minute
message: 'Too many rule evaluations'
});
app.post('/evaluate', ruleLimiter, (req, res) => {
const result = engine.evaluateExpr(rule, data);
res.json(result);
});
Depth Limits
Prevent deeply nested rules (DoS).
const engine = createRuleEngine({
maxDepth: 10, // Default: 10
maxOperators: 100 // Default: 100
});
// This will fail
const deepRule = {
and: [{ and: [{ and: [/* ... 20 levels deep ... */] }] }]
};
engine.evaluateExpr(deepRule, data);
// Error: "Rule exceeds maximum depth of 10"
Sensitive Data
Don’t expose sensitive data in error messages.
// Exposes sensitive data
try {
engine.evaluateExpr(rule, sensitiveData);
} catch (error) {
res.json({ error: error.message, data: sensitiveData });
}
Regex Safety
Prevent ReDoS (Regular Expression Denial of Service).
// ❌ Dangerous regex patterns
const unsafe = [
'(a+)+b', // Catastrophic backtracking
'(a|a)*b',
'(a*)*b'
];
// ✅ Safe regex patterns
const safe = [
'^[a-z]+@[a-z]+\\.[a-z]{2,}$', // Simple patterns
'^\\d{3}-\\d{3}-\\d{4}$'
];
// Validate regex before use
function isSafeRegex(pattern) {
// Check for dangerous patterns
const dangerous = [/\(\w\+\)\+/, /\(\w\*\)\*/];
return !dangerous.some(d => d.test(pattern));
}
Complete Security Checklist
✅ allowPrototypeAccess: false (default)
✅ Never override in production
✅ maxDepth: 10 (or lower)
✅ maxOperators: 100 (or lower)
✅ Limit requests per IP
✅ Limit evaluations per user
✅ Monitor for abuse
✅ Generic error messages
✅ Log errors privately
✅ Don't expose sensitive data
✅ Block dangerous patterns
✅ Timeout regex matching
✅ Test patterns before use
Secure Configuration
const engine = createRuleEngine({
// Security
allowPrototypeAccess: false, // Never true!
strict: true, // Prevent type coercion bugs
maxDepth: 10, // Limit nesting
maxOperators: 100, // Limit complexity
// Performance
enableCache: true,
maxCacheSize: 1000
});