We actively support the following versions with security updates:
| Version | Supported |
|---|---|
| 5.6.x | ✅ |
| 5.5.x | ✅ |
| 5.4.x | |
| < 5.4 | ❌ No longer supported |
We take the security of @mcabreradev/filter seriously. If you discover a security vulnerability, please follow these steps:
Please do not report security vulnerabilities through public GitHub issues.
Send your vulnerability report to:
Email: security@mcabreradev.com
Subject: [SECURITY] Brief description of the issue
- Description: Clear description of the vulnerability
- Impact: What an attacker could achieve
- Steps to Reproduce: Detailed steps to reproduce the issue
- Proof of Concept: Code example demonstrating the vulnerability
- Environment: Version of @mcabreradev/filter affected
- Suggested Fix: If you have ideas for fixing the issue
Subject: [SECURITY] SQL-like injection via filter expression
Description:
Unsanitized user input in filter expressions could allow malicious patterns
that cause excessive memory usage or CPU consumption.
Impact:
Denial of Service (DoS) through resource exhaustion
Steps to Reproduce:
1. Create a filter with deeply nested operators
2. Pass extremely large arrays in $in operator
3. Observe memory/CPU spike
Proof of Concept:
[Code example]
Environment:
- @mcabreradev/filter: 5.6.0
- Node.js: 20.0.0
Suggested Fix:
Add limits on expression depth and array sizes
- Acknowledgment: Within 48 hours of your report
- Initial Assessment: Within 7 days
- Regular Updates: Every 7 days until resolution
- Disclosure: Coordinated disclosure after fix is released
When using @mcabreradev/filter in production:
import { validateExpression, InvalidExpressionError } from '@mcabreradev/filter';
try {
const expression = validateExpression(userInput);
const results = filter(data, expression);
} catch (error) {
if (error instanceof InvalidExpressionError) {
// Handle invalid expression
}
}const ALLOWED_OPERATORS = ['$eq', '$ne', '$gt', '$gte', '$lt', '$lte'];
const ALLOWED_FIELDS = ['name', 'price', 'category'];
function sanitizeExpression(expr: any): any {
// Only allow whitelisted operators and fields
if (typeof expr !== 'object') return expr;
const sanitized: any = {};
for (const [key, value] of Object.entries(expr)) {
if (key.startsWith('$') && !ALLOWED_OPERATORS.includes(key)) {
continue; // Skip dangerous operators
}
if (!key.startsWith('$') && !ALLOWED_FIELDS.includes(key)) {
continue; // Skip non-whitelisted fields
}
sanitized[key] = sanitizeExpression(value);
}
return sanitized;
}import { filter } from '@mcabreradev/filter';
const MAX_ARRAY_SIZE = 10000;
const MAX_EXPRESSION_DEPTH = 5;
if (data.length > MAX_ARRAY_SIZE) {
throw new Error('Dataset too large');
}
// Limit expression depth
function checkDepth(expr: any, depth = 0): void {
if (depth > MAX_EXPRESSION_DEPTH) {
throw new Error('Expression too deep');
}
if (typeof expr === 'object') {
Object.values(expr).forEach(v => checkDepth(v, depth + 1));
}
}
checkDepth(expression);
const results = filter(data, expression);// Express.js example
import rateLimit from 'express-rate-limit';
const filterLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: 'Too many filter requests, please try again later'
});
app.get('/api/products', filterLimiter, (req, res) => {
// Filter logic
});TypeScript provides compile-time type safety:
import { filter, Expression } from '@mcabreradev/filter';
interface Product {
id: number;
name: string;
price: number;
}
const safeFilter = (data: Product[], expr: Expression) => {
return filter<Product>(data, expr);
};The $regex operator uses JavaScript's RegExp. Be aware of:
- ReDoS (Regular Expression Denial of Service): Complex patterns can cause exponential backtracking
- Mitigation: Validate and limit regex patterns from user input
// Don't allow arbitrary regex from users
const SAFE_REGEX_PATTERN = /^[a-zA-Z0-9\s-_]+$/;
if (!SAFE_REGEX_PATTERN.test(userPattern)) {
throw new Error('Invalid regex pattern');
}Deeply nested objects can cause stack overflow:
- Default: maxDepth is set to 3
- Recommendation: Keep default or lower for untrusted input
filter(data, expression, { maxDepth: 3 }); // Default is safeProcessing very large datasets can cause memory issues:
- Use lazy evaluation for large datasets
- Implement pagination in your API
import { filterLazy, take } from '@mcabreradev/filter';
const results = filterLazy(largeDataset, expression);
const firstPage = take(results, 20); // Lazy evaluation- We follow coordinated disclosure
- Security advisories published on GitHub Security Advisories
- CVE IDs assigned for applicable vulnerabilities
- Credit given to reporters (unless you prefer anonymity)
Security updates are released as:
- Patch versions for non-breaking security fixes (e.g., 5.6.1 → 5.6.2)
- Minor versions if breaking changes are required (e.g., 5.6.x → 5.7.0)
Subscribe to releases to stay informed: https://github.com/mcabreradev/filter/releases
For security-related questions that are not vulnerability reports:
- Open a GitHub Discussion
- Email: security@mcabreradev.com
We thank the following security researchers for responsible disclosure:
Last updated: November 4, 2025