
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
filter-expression
Advanced tools
Compact, safe expression DSL for filtering JSON-like data.
Compile a string expression once and evaluate it against many records — no eval.
npm i filter-expression
import { compile } from 'filter-expression';
const expr = compile("user.age >= 18 and country == 'US'");
const ok = expr.evaluate({ user: { age: 22 }, country: 'US' }); // true
compile(source: string, options?: CompileOptions): CompiledExpression
CompiledExpression.evaluate(record: unknown): booleanCompileOptions
caseInsensitive?: boolean — lowercases string comparisons and regexmaxDepth?: number — guard against runaway recursion (default 128)disallowRegex?: boolean — make regex(...) always return falseeval; guarded property access; regex opt-outin/nin, and regex| Function | Description |
|---|---|
compile(source, options?) | Parses and compiles an expression into a reusable evaluator. |
| Option | Type | Default | Notes |
|---|---|---|---|
caseInsensitive | boolean | false | Lowercases strings and adds i to regex if missing. |
maxDepth | number | 128 | Evaluation depth guard. |
disallowRegex | boolean | false | Forces regex(...) to return false. |
'abc', numbers 123, booleans true/false, nulluser.address.cityand, or, not==, !=, >, >=, <, <=in (...), nin (...)regex(valueExpr, 'pattern', 'flags?')Precedence: not > comparisons/in/regex > and > or. Use parentheses to group.
compile("price >= 10 and price <= 20");
compile("country in ('US','CA') and not user.banned");
compile("regex(email, '@example\\.com$', 'i')");
compile("name == 'Alice' or name == 'Bob'");
import { compile } from 'filter-expression';
// 1) Numbers and strings
compile('price > 9.99 and currency == "USD"').evaluate({ price: 10, currency: 'USD' }); // true
compile('price <= 5').evaluate({ price: 3 }); // true
compile("name == 'Alice'").evaluate({ name: 'alice' }); // false (case-sensitive by default)
// 2) Case-insensitive mode
compile("name == 'alice'", { caseInsensitive: true }).evaluate({ name: 'Alice' }); // true
compile('country < "b"', { caseInsensitive: true }).evaluate({ country: 'AZ' }); // true (lexicographic)
// 3) Logical precedence and grouping
// not > (comparisons/in/regex) > and > or
compile('true and false or true').evaluate({}); // true => (true and false) or true
compile('not (false or true) and true').evaluate({}); // false
// 4) Membership (IN / NIN)
compile("status in ('new','paid','shipped')").evaluate({ status: 'paid' }); // true
compile('code nin (200, 201, 204)').evaluate({ code: 404 }); // true
compile('num in (1, 2, 3)').evaluate({ num: 2 }); // true
// 5) Regex
compile("regex(email, '@example\\.com$')").evaluate({ email: 'user@example.com' }); // true
compile("regex(msg, '^hello', 'i')").evaluate({ msg: 'Hello world' }); // true
// With caseInsensitive option, an 'i' flag is added implicitly for comparisons and regex
compile("regex(text, 'world')", { caseInsensitive: true }).evaluate({ text: 'Hello World' }); // true
// 6) Null / undefined semantics
// Missing paths resolve to undefined
compile('user.age == null').evaluate({}); // true (both sides nullish)
compile('user.age != null').evaluate({ user: {} }); // false
compile("user.name == 'Alice'").evaluate({}); // false (undefined == 'Alice')
// 7) Numeric coercion where reasonable
// If both sides can be parsed as numbers, numeric comparison is used
compile('age >= "18"').evaluate({ age: 20 }); // true
compile('"10" < 2').evaluate({}); // false (10 < 2 is false)
// 8) Options guards
compile("regex(text, '.*')", { disallowRegex: true }).evaluate({ text: 'any' }); // false (regex disabled)
compile('not not not true', { maxDepth: 10 }).evaluate({}); // works (depth guard for pathological cases)
// 9) Nested property access and safety
compile('user.address.city == "NYC"').evaluate({ user: { address: { city: 'NYC' } } }); // true
// Access to forbidden keys is blocked and treated as undefined
compile('obj.__proto__ == null').evaluate({ obj: {} }); // true
eval/Function — expressions are tokenized, parsed to an AST, and interpreted.__proto__, prototype, constructor are blocked.undefined, comparisons against null/undefined are predictable.disallowRegex: true.maxDepth is exceeded.in (...) uses a Set internally for O(1) membership checks.Example run (Node.js, local laptop), using the built dist with warmup and multiple runs:
npm run build
N=100000 WARMUP=1 RUNS=5 node --expose-gc benchmarks/run.mjs
Sample output:
compile-once evaluate-many (num range): median 5.63 ms (17,746,884 ops/sec) [min 5.55 ms, max 6.47 ms]
compile-once evaluate-many (age & active): median 7.09 ms (14,107,938 ops/sec) [min 6.75 ms, max 8.01 ms]
compile-once evaluate-many (IN set): median 16.44 ms (6,084,576 ops/sec) [min 16.14 ms, max 18.45 ms]
compile-once evaluate-many (regex i): median 6.97 ms (14,350,976 ops/sec) [min 6.90 ms, max 8.88 ms]
parse+evaluate each time (num range): median 107.60 ms (929,382 ops/sec) [min 106.34 ms, max 108.75 ms]
Notes:
N, WARMUP, RUNS.node --expose-gc to allow optional GC between runs for more stable medians.exports map; types in distsideEffects: false)git clone <this-repo>
cd filter-expression
npm i
npm run check && npm test && npm run build
Please run tests and lints before submitting PRs.
See GitHub releases or future CHANGELOG.md.
strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes)..d.ts declarations.MIT
FAQs
Compact, safe expression DSL for filtering JSON-like data.
We found that filter-expression demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.