Injection

Injection Guide: Node.js (Express) [Mar 2026] [CVE-2026-22738]

[Updated March 2026] Updated CVE-2026-22738

Overview

CVE-2026-22738 describes a SpEL injection vulnerability in Spring AI where a user-supplied value is used as a filter expression key inside SimpleVectorStore. If an attacker provides crafted input, SpEL can be evaluated by the runtime, potentially allowing arbitrary code execution on affected deployments. The vulnerability affects Spring AI: from 1.0.0 before 1.0.5, and from 1.1.0 before 1.1.4. In Node.js/Express, this vulnerability class surfaces when untrusted input is used to drive executable logic-such as building a JavaScript predicate with eval or Function, or using user input to select or construct query predicates without validation. An attacker could pass a filter key that is interpreted as code, leading to code execution, data exposure, or server compromise. The CVE highlights the danger of evaluating user-supplied expressions; the Node.js counterpart is to avoid dynamic evaluation entirely. Remediation involves hardening input handling, validating filters, and using safe APIs instead of dynamic evaluation.

Affected Versions

N/A (Java Spring AI CVE; not applicable to Node.js/Express)

Code Fix Example

Node.js (Express) API Security Remediation
// Vulnerable pattern (execution of user input as code)
const express = require('express');
const app = express();

const data = [
  { id: 1, name: 'Alice', role: 'admin' },
  { id: 2, name: 'Bob',   role: 'user'  },
  { id: 3, name: 'Charlie', role: 'user'  }
];

app.get('/vuln/search', (req, res) => {
  const filterKey = req.query.filterKey; // user-supplied
  const value = req.query.value;         // user-supplied

  // WARNING: executing user-supplied code can lead to remote code execution
  const predicate = new Function('item', 'return item[' + JSON.stringify(filterKey) + '] == ' + JSON.stringify(value) + ';');
  const result = data.filter(item => predicate(item));
  res.json(result);
});

// Safe pattern: whitelist keys and compare safely
app.get('/safe/search', (req, res) => {
  const filterKey = req.query.filterKey;
  const value = req.query.value;
  const allowedKeys = ['id', 'name', 'role'];
  if (!allowedKeys.includes(filterKey)) {
    return res.status(400).send('Invalid filter');
  }

  const result = data.filter(item => {
    const itemValue = item[filterKey];
    if (typeof itemValue === 'number') {
      const n = Number(value);
      return !Number.isNaN(n) && itemValue === n;
    }
    return String(itemValue) === String(value);
  });
  res.json(result);
});

app.listen(3000, () => console.log('Server running on port 3000'));

CVE References

Choose which optional cookies to allow. You can change this any time.