HPP - HTTP Parameter Pollution Protection

0.2.3 · maintenance · verified Wed Apr 22

`hpp` is an Express middleware designed to protect web applications from HTTP Parameter Pollution (HPP) attacks. HPP exploits how web frameworks handle multiple parameters with the same name in a single request. This library, currently at version 0.2.3, mitigates this by identifying array parameters in `req.query` and `req.body` (specifically for `application/x-www-form-urlencoded` requests) and assigning only the *last* parameter value to the main `req.query` or `req.body` object. The original, potentially polluted array of values is moved to `req.queryPolluted` or `req.bodyPolluted` for inspection. This ensures that downstream middleware or route handlers only receive a single, consistent value for each parameter, preventing attackers from bypassing input validation or causing unexpected application behavior. It's a low-level security utility, likely in maintenance mode given its stable version and specific scope, and integrates directly into the Express middleware chain.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates how to integrate `hpp` middleware into an Express application to protect against HTTP Parameter Pollution. It shows basic usage, how polluted parameters are moved to `req.queryPolluted` and `req.bodyPolluted`, and an example of whitelisting specific parameters for certain routes.

import express from 'express';
import hpp from 'hpp';
import bodyParser from 'body-parser';

const app = express();
const port = 3000;

// Make sure body-parser is used BEFORE hpp to allow hpp to process req.body.
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json()); // Optional, but common. HPP only checks urlencoded for body.

// Add the HPP middleware. This secures all routes by default.
// It will move polluted parameters from req.query and req.body to req.queryPolluted and req.bodyPolluted.
app.use(hpp());

// Example route to demonstrate HPP's effect
app.get('/search', (req: express.Request, res: express.Response) => {
  console.log('Original req.query (after HPP):', req.query);
  console.log('Polluted req.query (if any):', req.queryPolluted);
  res.send(`Search results for: ${req.query.q || 'N/A'}. Polluted: ${JSON.stringify(req.queryPolluted || {})}`);
});

app.post('/submit', (req: express.Request, res: express.Response) => {
    console.log('Original req.body (after HPP):', req.body);
    console.log('Polluted req.body (if any):', req.bodyPolluted);
    res.send(`Submitted: ${req.body.item || 'N/A'}. Polluted: ${JSON.stringify(req.bodyPolluted || {})}`);
});

// Whitelisting example (as per README suggestion)
// If a specific route requires array parameters, apply HPP with a whitelist option.
app.get('/multi-select', hpp({ whitelist: ['selectedIds'] }), (req: express.Request, res: express.Response) => {
    // For /multi-select?selectedIds=1&selectedIds=2
    // req.query.selectedIds will be ['1', '2'] because of the whitelist here.
    console.log('Multi-select req.query:', req.query);
    res.send(`Selected IDs: ${req.query.selectedIds}`);
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
  console.log(`Test with:`);
  console.log(`GET http://localhost:${port}/search?q=item1&q=item2`);
  console.log(`POST http://localhost:${port}/submit -d "item=val1&item=val2" -H "Content-Type: application/x-www-form-urlencoded"`);
  console.log(`GET http://localhost:${port}/multi-select?selectedIds=100&selectedIds=200`);
});

view raw JSON →