Unvalidated dynamic method calls

Calling dynamically selected methods without validation

Description

Calling an object property selected by user input can invoke a nonexistent or inherited method and raise a runtime exception. An uncaught exception during request handling may affect availability. The input may also select a method that the application did not intend to expose.

Potential impact

  • Calling a nonexistent function may throw an exception in a request handler and reduce availability.
  • An attacker may supply an unsupported action name to invoke an internal method.
  • Calling properties on the prototype chain may produce unintended behavior.

Remediation

  • Use an explicit switch or allow-list instead of selecting methods directly from user input.
  • If dynamic lookup is necessary, check that the property is owned by the object with Object.hasOwn or hasOwnProperty, and verify typeof value === "function".
  • Reject unsupported actions by default.

Examples

Before

javascript
const actions = {
  play(data) {
    return data;
  },
};

app.get("/perform/:action", (req, res) => {
  res.send(actions[req.params.action](req.query.payload));
});

After

javascript
const actions = Object.freeze({
  play(data) {
    return data;
  },
});

app.get("/perform/:action", (req, res) => {
  const action = actions[req.params.action];
  if (!Object.hasOwn(actions, req.params.action) || typeof action !== "function") {
    return res.status(400).send("Unsupported action");
  }
  return res.send(action(req.query.payload));
});

Explanation:

  • Before: Input is used directly as the object key for a function call. An invalid key may cause an exception or select an unintended property.
  • After: The handler calls the value only after checking that it is an allowed own property and a function.

References