@@ -499,6 +499,125 @@ describe('proxyaddr.compile(trust)', function () {
499499 } )
500500} )
501501
502+ describe ( 'proxyaddr.compile(trust) IPv4-mapped IPv6 subnets' , function ( ) {
503+ // @see https://github.com/jshttp/proxy-addr/security/advisories/GHSA-jqcg-44mw-7w3h
504+ it ( 'should not trust arbitrary IPv4 for a short-prefix mapped subnet' , function ( ) {
505+ var trust = proxyaddr . compile ( [ '::ffff:10.0.0.0/8' ] )
506+ assert . strictEqual ( trust ( '8.8.8.8' ) , false )
507+ assert . strictEqual ( trust ( '203.0.113.9' ) , false )
508+ assert . strictEqual ( trust ( '0.0.0.0' ) , false )
509+ assert . strictEqual ( trust ( '10.0.0.1' ) , false )
510+ } )
511+
512+ it ( 'should trust the intended block when written as a /104 mapped subnet' , function ( ) {
513+ var trust = proxyaddr . compile ( [ '::ffff:10.0.0.0/104' ] )
514+ assert . strictEqual ( trust ( '10.0.0.1' ) , true )
515+ assert . strictEqual ( trust ( '8.8.8.8' ) , false )
516+ } )
517+
518+ it ( 'should behave like the plain IPv4 subnet' , function ( ) {
519+ var trust = proxyaddr . compile ( [ '10.0.0.0/8' ] )
520+ assert . strictEqual ( trust ( '10.0.0.1' ) , true )
521+ assert . strictEqual ( trust ( '8.8.8.8' ) , false )
522+ } )
523+
524+ it ( 'should treat a /96 mapped subnet as all IPv4' , function ( ) {
525+ var trust = proxyaddr . compile ( [ '::ffff:0.0.0.0/96' ] )
526+ assert . strictEqual ( trust ( '10.0.0.1' ) , true )
527+ assert . strictEqual ( trust ( '8.8.8.8' ) , true )
528+ } )
529+
530+ it ( 'should reject a mapped subnet whose prefix is below 96' , function ( ) {
531+ var trust = proxyaddr . compile ( [ '::ffff:0.0.0.0/95' ] )
532+ assert . strictEqual ( trust ( '8.8.8.8' ) , false )
533+ } )
534+
535+ it ( 'should honor a /97 mapped subnet as a proper subset of IPv4' , function ( ) {
536+ var trust = proxyaddr . compile ( [ '::ffff:0.0.0.0/97' ] )
537+ assert . strictEqual ( trust ( '8.8.8.8' ) , true )
538+ assert . strictEqual ( trust ( '120.0.0.1' ) , true )
539+ assert . strictEqual ( trust ( '200.0.0.1' ) , false )
540+ } )
541+
542+ it ( 'should not trust IPv4 for an IPv6 subnet with zero leading bits' , function ( ) {
543+ var trust = proxyaddr . compile ( [ '::/1' ] )
544+ assert . strictEqual ( trust ( '8.8.8.8' ) , false )
545+ assert . strictEqual ( trust ( '::ffff:8.8.8.8' ) , false )
546+ assert . strictEqual ( trust ( '::ffff:10.0.0.1' ) , false )
547+ } )
548+
549+ it ( 'should leave ordinary IPv6 subnets unaffected' , function ( ) {
550+ var trust = proxyaddr . compile ( [ 'fc00::/7' ] )
551+ assert . strictEqual ( trust ( '8.8.8.8' ) , false )
552+ assert . strictEqual ( trust ( 'fc00::1' ) , true )
553+ } )
554+
555+ it ( 'should leave the built-in uniquelocal name unaffected' , function ( ) {
556+ var trust = proxyaddr . compile ( 'uniquelocal' )
557+ assert . strictEqual ( trust ( '10.0.0.1' ) , true )
558+ assert . strictEqual ( trust ( '8.8.8.8' ) , false )
559+ } )
560+
561+ it ( 'should neutralize a short-prefix mapped subnet in a multi-subnet list' , function ( ) {
562+ var trust = proxyaddr . compile ( [ '::ffff:10.0.0.0/8' , '10.0.0.0/8' ] )
563+ assert . strictEqual ( trust ( '10.0.0.1' ) , true )
564+ assert . strictEqual ( trust ( '8.8.8.8' ) , false )
565+ } )
566+
567+ it ( 'should not believe X-Forwarded-For from an untrusted socket peer' , function ( ) {
568+ var req = createReq ( '127.0.0.1' , {
569+ 'x-forwarded-for' : '9.9.9.9'
570+ } )
571+ assert . strictEqual ( proxyaddr ( req , [ '::ffff:10.0.0.0/8' ] ) , '127.0.0.1' )
572+ } )
573+
574+ it ( 'should not trust an IPv4-mapped candidate for a short-prefix mapped subnet' , function ( ) {
575+ var trust = proxyaddr . compile ( [ '::ffff:10.0.0.0/8' ] )
576+ assert . strictEqual ( trust ( '::ffff:8.8.8.8' ) , false )
577+ assert . strictEqual ( trust ( '::ffff:1.2.3.4' ) , false )
578+ assert . strictEqual ( trust ( '::ffff:10.0.0.1' ) , false )
579+ } )
580+
581+ it ( 'should trust an IPv4-mapped candidate for a /104 mapped subnet' , function ( ) {
582+ var trust = proxyaddr . compile ( [ '::ffff:10.0.0.0/104' ] )
583+ assert . strictEqual ( trust ( '::ffff:10.0.0.1' ) , true )
584+ assert . strictEqual ( trust ( '::ffff:8.8.8.8' ) , false )
585+ } )
586+
587+ it ( 'should match a mapped candidate identically to its IPv4 form' , function ( ) {
588+ var trust = proxyaddr . compile ( [ '10.0.0.0/8' ] )
589+ assert . strictEqual ( trust ( '::ffff:10.0.0.1' ) , true )
590+ assert . strictEqual ( trust ( '::ffff:8.8.8.8' ) , false )
591+ } )
592+
593+ it ( 'should not believe X-Forwarded-For from an untrusted IPv4-mapped socket peer' , function ( ) {
594+ var req = createReq ( '::ffff:8.8.8.8' , {
595+ 'x-forwarded-for' : '9.9.9.9'
596+ } )
597+ assert . strictEqual ( proxyaddr ( req , [ '::ffff:10.0.0.0/8' ] ) , '::ffff:8.8.8.8' )
598+ } )
599+
600+ it ( 'should not trust native IPv6 for a short-prefix mapped subnet' , function ( ) {
601+ var trust = proxyaddr . compile ( [ '::ffff:10.0.0.0/8' ] )
602+ assert . strictEqual ( trust ( '::1' ) , false )
603+ assert . strictEqual ( trust ( '::abcd' ) , false )
604+ var trust95 = proxyaddr . compile ( [ '::ffff:0.0.0.0/95' ] )
605+ assert . strictEqual ( trust95 ( '::fffe:0:0' ) , false )
606+ } )
607+
608+ it ( 'should not trust native IPv6 for a valid mapped subnet' , function ( ) {
609+ var trust = proxyaddr . compile ( [ '::ffff:10.0.0.0/104' ] )
610+ assert . strictEqual ( trust ( '::1' ) , false )
611+ assert . strictEqual ( trust ( '10.0.0.1' ) , true )
612+ } )
613+
614+ it ( 'should still trust native IPv6 within an ordinary IPv6 subnet' , function ( ) {
615+ var trust = proxyaddr . compile ( [ '2001:db8::/32' ] )
616+ assert . strictEqual ( trust ( '2001:db8::1' ) , true )
617+ assert . strictEqual ( trust ( '::1' ) , false )
618+ } )
619+ } )
620+
502621function createReq ( socketAddr , headers ) {
503622 return {
504623 connection : {
0 commit comments