• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / storage / 23329701930

20 Mar 2026 04:56AM UTC coverage: 76.605% (+0.03%) from 76.571%
23329701930

Pull #921

github

web-flow
Merge ead80fa04 into 003d5f5df
Pull Request #921: fix: validate response headers before sending, prevent invalid transform input

4081 of 5793 branches covered (70.45%)

Branch coverage included in aggregate %.

62 of 71 new or added lines in 5 files covered. (87.32%)

26977 of 34750 relevant lines covered (77.63%)

186.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.33
/src/http/plugins/header-validator.ts
1
import { ERRORS } from '@internal/errors'
2✔
2
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
2✔
3
import fastifyPlugin from 'fastify-plugin'
2✔
4

2✔
5
/**
2✔
6
 * Matches invalid HTTP header characters per RFC 7230 field-vchar specification.
2✔
7
 * Valid: TAB (0x09), visible ASCII (0x20-0x7E), obs-text (0x80-0xFF).
2✔
8
 * Invalid: control characters (0x00-0x1F except TAB) and DEL (0x7F).
2✔
9
 * @see https://tools.ietf.org/html/rfc7230#section-3.2
2✔
10
 */
2✔
11
const INVALID_HEADER_CHAR_PATTERN = /[^\t\x20-\x7e\x80-\xff]/
2✔
12

2✔
13
interface HeaderValidatorOptions {
2✔
14
  excludeUrls?: string[]
2✔
15
}
2✔
16

2✔
17
/**
2✔
18
 * Validates response headers before they're sent to prevent ERR_INVALID_CHAR crashes.
2✔
19
 *
2✔
20
 * Node.js throws ERR_INVALID_CHAR during writeHead() if headers contain control characters.
2✔
21
 * This hook validates headers in onSend (before writeHead) and throws InvalidHeaderChar error
2✔
22
 */
2✔
23
export const headerValidator = (options: HeaderValidatorOptions = {}) =>
2✔
24
  fastifyPlugin(
266✔
25
    async function headerValidatorPlugin(fastify: FastifyInstance) {
266✔
26
      fastify.addHook('onSend', async (request: FastifyRequest, reply: FastifyReply, payload) => {
266✔
27
        if (options.excludeUrls?.includes(request.url.toLowerCase())) {
286!
NEW
28
          return payload
×
NEW
29
        }
×
30

286✔
31
        const headers = Object.entries(reply.getHeaders())
286✔
32
        for (const [key, value] of headers) {
286✔
33
          if (typeof value === 'string' && INVALID_HEADER_CHAR_PATTERN.test(value)) {
462✔
NEW
34
            throw ERRORS.InvalidHeaderChar(key, value)
×
35
          } else if (Array.isArray(value)) {
462!
NEW
36
            for (let item of value) {
×
NEW
37
              if (typeof item === 'string' && INVALID_HEADER_CHAR_PATTERN.test(item)) {
×
NEW
38
                throw ERRORS.InvalidHeaderChar(key, item)
×
NEW
39
              }
×
NEW
40
            }
×
NEW
41
          }
×
42
        }
462✔
43

286✔
44
        return payload
286✔
45
      })
266✔
46
    },
266✔
47
    { name: 'header-validator' }
266✔
48
  )
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc