88
99import {
1010 getFirstHeaderValue ,
11+ normalizeTrustProxyHeaders ,
1112 sanitizeRequestHeaders ,
1213 validateRequest ,
1314 validateUrl ,
@@ -37,6 +38,35 @@ describe('Validation Utils', () => {
3738 } ) ;
3839 } ) ;
3940
41+ describe ( 'normalizeTrustProxyHeaders' , ( ) => {
42+ it ( 'should return an empty set when input is undefined' , ( ) => {
43+ expect ( normalizeTrustProxyHeaders ( undefined ) ) . toEqual ( new Set ( ) ) ;
44+ } ) ;
45+
46+ it ( 'should return an empty set when input is false' , ( ) => {
47+ expect ( normalizeTrustProxyHeaders ( false ) ) . toEqual ( new Set ( ) ) ;
48+ } ) ;
49+
50+ it ( 'should return a set containing "*" when input is true' , ( ) => {
51+ expect ( normalizeTrustProxyHeaders ( true ) ) . toEqual ( new Set ( [ '*' ] ) ) ;
52+ } ) ;
53+
54+ it ( 'should return a set of lowercased header names when input is an array of strings' , ( ) => {
55+ expect ( normalizeTrustProxyHeaders ( [ 'X-Forwarded-Host' , 'X-Forwarded-Proto' ] ) ) . toEqual (
56+ new Set ( [ 'x-forwarded-host' , 'x-forwarded-proto' ] ) ,
57+ ) ;
58+ } ) ;
59+
60+ it ( 'should throw an error if input array contains "*"' , ( ) => {
61+ expect ( ( ) => normalizeTrustProxyHeaders ( [ '*' ] ) ) . toThrowError (
62+ '"*" is not allowed as a value for the "trustProxyHeaders" option.' ,
63+ ) ;
64+ expect ( ( ) => normalizeTrustProxyHeaders ( [ 'X-Forwarded-Host' , '*' ] ) ) . toThrowError (
65+ '"*" is not allowed as a value for the "trustProxyHeaders" option.' ,
66+ ) ;
67+ } ) ;
68+ } ) ;
69+
4070 describe ( 'validateUrl' , ( ) => {
4171 const allowedHosts = new Set ( [ 'example.com' , '*.google.com' ] ) ;
4272
@@ -224,23 +254,37 @@ describe('Validation Utils', () => {
224254 'x-forwarded-proto' : 'https' ,
225255 } ,
226256 } ) ;
227- const secured = sanitizeRequestHeaders ( req , new Set ( ) ) ;
257+ const secured = sanitizeRequestHeaders ( req , normalizeTrustProxyHeaders ( undefined ) ) ;
228258
229259 expect ( secured . headers . get ( 'host' ) ) . toBe ( 'example.com' ) ;
230260 expect ( secured . headers . has ( 'x-forwarded-host' ) ) . toBeFalse ( ) ;
231261 expect ( secured . headers . has ( 'x-forwarded-proto' ) ) . toBeFalse ( ) ;
232262 } ) ;
233263
234- it ( 'should retain allowed proxy headers when explicitly provided' , ( ) => {
235- const trustProxyHeaders = new Set ( [ 'x-forwarded-host' ] ) ;
264+ it ( 'should scrub unallowed proxy headers when trustProxyHeaders is false' , ( ) => {
265+ const req = new Request ( 'http://example.com' , {
266+ headers : {
267+ 'host' : 'example.com' ,
268+ 'x-forwarded-host' : 'evil.com' ,
269+ 'x-forwarded-proto' : 'https' ,
270+ } ,
271+ } ) ;
272+ const secured = sanitizeRequestHeaders ( req , normalizeTrustProxyHeaders ( false ) ) ;
273+
274+ expect ( secured . headers . get ( 'host' ) ) . toBe ( 'example.com' ) ;
275+ expect ( secured . headers . has ( 'x-forwarded-host' ) ) . toBeFalse ( ) ;
276+ expect ( secured . headers . has ( 'x-forwarded-proto' ) ) . toBeFalse ( ) ;
277+ } ) ;
278+
279+ it ( 'should only retain allowed proxy headers when explicitly provided' , ( ) => {
236280 const req = new Request ( 'http://example.com' , {
237281 headers : {
238282 'host' : 'example.com' ,
239283 'x-forwarded-host' : 'proxy.com' ,
240284 'x-forwarded-proto' : 'https' ,
241285 } ,
242286 } ) ;
243- const secured = sanitizeRequestHeaders ( req , trustProxyHeaders ) ;
287+ const secured = sanitizeRequestHeaders ( req , normalizeTrustProxyHeaders ( [ 'x-forwarded-host' ] ) ) ;
244288
245289 expect ( secured . headers . get ( 'host' ) ) . toBe ( 'example.com' ) ;
246290 expect ( secured . headers . get ( 'x-forwarded-host' ) ) . toBe ( 'proxy.com' ) ;
@@ -253,23 +297,22 @@ describe('Validation Utils', () => {
253297 'host' : 'example.com' ,
254298 'x-forwarded-host' : 'proxy.com' ,
255299 'x-forwarded-proto' : 'https' ,
300+ 'x-forwarded-email' : 'user@example.com' ,
256301 } ,
257302 } ) ;
258- const secured = sanitizeRequestHeaders (
259- req ,
260- new Set ( [ 'x-forwarded-host' , 'x-forwarded-proto' ] ) ,
261- ) ;
303+ const secured = sanitizeRequestHeaders ( req , normalizeTrustProxyHeaders ( true ) ) ;
262304
263305 expect ( secured . headers . get ( 'host' ) ) . toBe ( 'example.com' ) ;
264306 expect ( secured . headers . get ( 'x-forwarded-host' ) ) . toBe ( 'proxy.com' ) ;
265307 expect ( secured . headers . get ( 'x-forwarded-proto' ) ) . toBe ( 'https' ) ;
308+ expect ( secured . headers . get ( 'x-forwarded-email' ) ) . toBe ( 'user@example.com' ) ;
266309 } ) ;
267310
268311 it ( 'should not clone the request if no proxy headers need to be removed' , ( ) => {
269312 const req = new Request ( 'http://example.com' , {
270313 headers : { 'accept' : 'application/json' } ,
271314 } ) ;
272- const secured = sanitizeRequestHeaders ( req , new Set ( ) ) ;
315+ const secured = sanitizeRequestHeaders ( req , normalizeTrustProxyHeaders ( false ) ) ;
273316
274317 expect ( secured ) . toBe ( req ) ;
275318 expect ( secured . headers . get ( 'accept' ) ) . toBe ( 'application/json' ) ;
0 commit comments