@@ -83,8 +83,12 @@ const suppressErrorsOption = bindConfig(
8383
8484const allowPrivateAddressOption = bindConfig (
8585 flag ( "-p" , "--allow-private-address" , {
86- description :
87- message `Allow private IP addresses for explicit lookup/traverse requests.` ,
86+ description : message `Allow private IP addresses for URLs discovered \
87+ during traversal. This option only has an effect when used together \
88+ with ${ optionNames ( [ "-t" , "--traverse" ] ) } , since URLs explicitly \
89+ provided on the command line always allow private addresses and \
90+ recursive fetches via ${ optionNames ( [ "--recurse" ] ) } always disallow \
91+ them.` ,
8892 } ) ,
8993 {
9094 context : configContext ,
@@ -716,6 +720,20 @@ export async function runLookup(
716720 } ) . start ( ) ;
717721
718722 let server : TemporaryServer | undefined = undefined ;
723+ // URLs explicitly provided by the user always allow private addresses,
724+ // so that local servers can be looked up without -p/--allow-private-address.
725+ // URLs discovered during traversal follow the option to mitigate SSRF
726+ // against private addresses, while recursive fetches always disallow
727+ // private addresses regardless of the option (see the --recurse branch
728+ // below, which hardcodes `allowPrivateAddress: false`).
729+ const initialBaseDocumentLoader = await getDocumentLoader ( {
730+ userAgent : command . userAgent ,
731+ allowPrivateAddress : true ,
732+ } ) ;
733+ const initialDocumentLoader = wrapDocumentLoaderWithTimeout (
734+ initialBaseDocumentLoader ,
735+ command . timeout ,
736+ ) ;
719737 const baseDocumentLoader = await getDocumentLoader ( {
720738 userAgent : command . userAgent ,
721739 allowPrivateAddress : command . allowPrivateAddress ,
@@ -734,6 +752,7 @@ export async function runLookup(
734752 ) ;
735753
736754 let authLoader : DocumentLoader | undefined = undefined ;
755+ let initialAuthLoader : DocumentLoader | undefined = undefined ;
737756 let authIdentity :
738757 | { keyId : URL ; privateKey : CryptoKey }
739758 | undefined = undefined ;
@@ -836,6 +855,24 @@ export async function runLookup(
836855 baseAuthLoader ,
837856 command . timeout ,
838857 ) ;
858+ const initialBaseAuthLoader = getAuthenticatedDocumentLoader (
859+ authIdentity ,
860+ {
861+ allowPrivateAddress : true ,
862+ userAgent : command . userAgent ,
863+ specDeterminer : {
864+ determineSpec ( ) {
865+ return command . firstKnock ;
866+ } ,
867+ rememberSpec ( ) {
868+ } ,
869+ } ,
870+ } ,
871+ ) ;
872+ initialAuthLoader = wrapDocumentLoaderWithTimeout (
873+ initialBaseAuthLoader ,
874+ command . timeout ,
875+ ) ;
839876 }
840877
841878 spinner . text = `Looking up the ${
@@ -885,8 +922,8 @@ export async function runLookup(
885922 command . timeout ,
886923 )
887924 : undefined ;
888- const initialLookupDocumentLoader : DocumentLoader = authLoader ??
889- documentLoader ;
925+ const initialLookupDocumentLoader : DocumentLoader = initialAuthLoader ??
926+ initialDocumentLoader ;
890927 const recursiveLookupDocumentLoader : DocumentLoader = recursiveAuthLoader ??
891928 recursiveDocumentLoader ;
892929 let totalObjects = 0 ;
@@ -1109,7 +1146,7 @@ export async function runLookup(
11091146 let collection : APObject | null = null ;
11101147 try {
11111148 collection = await effectiveDeps . lookupObject ( url , {
1112- documentLoader : authLoader ?? documentLoader ,
1149+ documentLoader : initialAuthLoader ?? initialDocumentLoader ,
11131150 contextLoader,
11141151 userAgent : command . userAgent ,
11151152 } ) ;
@@ -1248,7 +1285,7 @@ export async function runLookup(
12481285 for ( const url of command . urls ) {
12491286 promises . push (
12501287 effectiveDeps . lookupObject ( url , {
1251- documentLoader : authLoader ?? documentLoader ,
1288+ documentLoader : initialAuthLoader ?? initialDocumentLoader ,
12521289 contextLoader,
12531290 userAgent : command . userAgent ,
12541291 } ) . catch ( ( error ) => {
0 commit comments