File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -57,6 +57,22 @@ const supportedProtocols = platform.protocols.map((protocol) => {
5757 return protocol + ':' ;
5858} ) ;
5959
60+ // Node's WHATWG URL parser returns `username` and `password` percent-encoded.
61+ // Decode before composing the `auth` option so credentials such as
62+ // `my%40email.com:pass` are sent as `my@email.com:pass`. Falls back to the
63+ // original value for malformed input so a bad encoding never throws.
64+ const decodeURIComponentSafe = ( value ) => {
65+ if ( ! utils . isString ( value ) ) {
66+ return value ;
67+ }
68+
69+ try {
70+ return decodeURIComponent ( value ) ;
71+ } catch ( error ) {
72+ return value ;
73+ }
74+ } ;
75+
6076const flushOnFinish = ( stream , [ throttled , flush ] ) => {
6177 stream . on ( 'end' , flush ) . on ( 'error' , flush ) ;
6278
@@ -650,8 +666,8 @@ export default isHttpAdapterSupported &&
650666 }
651667
652668 if ( ! auth && parsed . username ) {
653- const urlUsername = parsed . username ;
654- const urlPassword = parsed . password ;
669+ const urlUsername = decodeURIComponentSafe ( parsed . username ) ;
670+ const urlPassword = decodeURIComponentSafe ( parsed . password ) ;
655671 auth = urlUsername + ':' + urlPassword ;
656672 }
657673
Original file line number Diff line number Diff line change @@ -890,6 +890,44 @@ describe('supports http with nodejs', () => {
890890 }
891891 } ) ;
892892
893+ it ( 'should decode basic auth credentials from the request URL' , async ( ) => {
894+ const server = await startHTTPServer (
895+ ( req , res ) => {
896+ res . end ( req . headers . authorization ) ;
897+ } ,
898+ { port : SERVER_PORT }
899+ ) ;
900+
901+ try {
902+ const response = await axios . get (
903+ `http://my%40email.com:pa%24ss@localhost:${ server . address ( ) . port } /`
904+ ) ;
905+ const base64 = Buffer . from ( 'my@email.com:pa$ss' , 'utf8' ) . toString ( 'base64' ) ;
906+ assert . strictEqual ( response . data , `Basic ${ base64 } ` ) ;
907+ } finally {
908+ await stopHTTPServer ( server ) ;
909+ }
910+ } ) ;
911+
912+ it ( 'keeps malformed URL credentials percent-encoding and does not throw' , async ( ) => {
913+ const server = await startHTTPServer (
914+ ( req , res ) => {
915+ res . end ( req . headers . authorization ) ;
916+ } ,
917+ { port : SERVER_PORT }
918+ ) ;
919+
920+ try {
921+ const response = await axios . get (
922+ `http://user%:foo%zz@localhost:${ server . address ( ) . port } /`
923+ ) ;
924+ const base64 = Buffer . from ( 'user%:foo%zz' , 'utf8' ) . toString ( 'base64' ) ;
925+ assert . strictEqual ( response . data , `Basic ${ base64 } ` ) ;
926+ } finally {
927+ await stopHTTPServer ( server ) ;
928+ }
929+ } ) ;
930+
893931 it ( 'should support basic auth with a header' , async ( ) => {
894932 const server = await startHTTPServer (
895933 ( req , res ) => {
You can’t perform that action at this time.
0 commit comments