hostHeaderValidation.js 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /**
  2. * Express middleware for DNS rebinding protection.
  3. * Validates Host header hostname (port-agnostic) against an allowed list.
  4. *
  5. * This is particularly important for servers without authorization or HTTPS,
  6. * such as localhost servers or development servers. DNS rebinding attacks can
  7. * bypass same-origin policy by manipulating DNS to point a domain to a
  8. * localhost address, allowing malicious websites to access your local server.
  9. *
  10. * @param allowedHostnames - List of allowed hostnames (without ports).
  11. * For IPv6, provide the address with brackets (e.g., '[::1]').
  12. * @returns Express middleware function
  13. *
  14. * @example
  15. * ```typescript
  16. * const middleware = hostHeaderValidation(['localhost', '127.0.0.1', '[::1]']);
  17. * app.use(middleware);
  18. * ```
  19. */
  20. export function hostHeaderValidation(allowedHostnames) {
  21. return (req, res, next) => {
  22. const hostHeader = req.headers.host;
  23. if (!hostHeader) {
  24. res.status(403).json({
  25. jsonrpc: '2.0',
  26. error: {
  27. code: -32000,
  28. message: 'Missing Host header'
  29. },
  30. id: null
  31. });
  32. return;
  33. }
  34. // Use URL API to parse hostname (handles IPv4, IPv6, and regular hostnames)
  35. let hostname;
  36. try {
  37. hostname = new URL(`http://${hostHeader}`).hostname;
  38. }
  39. catch {
  40. res.status(403).json({
  41. jsonrpc: '2.0',
  42. error: {
  43. code: -32000,
  44. message: `Invalid Host header: ${hostHeader}`
  45. },
  46. id: null
  47. });
  48. return;
  49. }
  50. if (!allowedHostnames.includes(hostname)) {
  51. res.status(403).json({
  52. jsonrpc: '2.0',
  53. error: {
  54. code: -32000,
  55. message: `Invalid Host: ${hostname}`
  56. },
  57. id: null
  58. });
  59. return;
  60. }
  61. next();
  62. };
  63. }
  64. /**
  65. * Convenience middleware for localhost DNS rebinding protection.
  66. * Allows only localhost, 127.0.0.1, and [::1] (IPv6 localhost) hostnames.
  67. *
  68. * @example
  69. * ```typescript
  70. * app.use(localhostHostValidation());
  71. * ```
  72. */
  73. export function localhostHostValidation() {
  74. return hostHeaderValidation(['localhost', '127.0.0.1', '[::1]']);
  75. }
  76. //# sourceMappingURL=hostHeaderValidation.js.map