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