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
switchor 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.hasOwnorhasOwnProperty, and verifytypeof 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.