@@ -47,7 +47,7 @@ export class DefaultReporter implements Reporter {
4747 private renderEmitter = new EventEmitter ( ) ;
4848 private progressState : ProgressState | null = null
4949 private verbosityToggleCallback : ( ( ) => void ) | null = null ;
50- private sudoPasswordSubmittedCallback : ( ( password : string ) => boolean ) | null = null ;
50+ private sudoPasswordSubmittedCallback : ( ( password : string ) => Promise < boolean > ) | null = null ;
5151 silent = false ;
5252
5353 constructor ( ) {
@@ -72,7 +72,7 @@ export class DefaultReporter implements Reporter {
7272 this . verbosityToggleCallback = callback ;
7373 }
7474
75- onSudoPasswordSubmitted ( callback : ( password : string ) => boolean ) : void {
75+ onSudoPasswordSubmitted ( callback : ( password : string ) => Promise < boolean > ) : void {
7676 this . sudoPasswordSubmittedCallback = callback ;
7777 }
7878
@@ -199,13 +199,14 @@ export class DefaultReporter implements Reporter {
199199 }
200200
201201 async promptSudo ( pluginName : string , data : CommandRequestData , secureMode : boolean ) : Promise < string | undefined > {
202- ctx . log ( chalk . blue ( `Plugin: "${ pluginName } " requires root access to run command: "sudo ${ data . command } "` ) ) ;
202+ ctx . log ( `Plugin: "${ pluginName } " requires root access to run command: "sudo ${ data . command } "` ) ;
203+ const title = `Plugin: "${ pluginName } " requires root access to run command: "sudo ${ data . command } "` ;
203204
204205 let password ;
205206
206207 // Password is only needed outside of sudo timeout. Pass password in as undefined if not needed.
207- if ( secureMode || ! SudoUtils . validate ( ) ) {
208- password = await this . getUserPassword ( ) ;
208+ if ( secureMode || ! ( await SudoUtils . validate ( ) ) ) {
209+ password = await this . getUserPassword ( title ) ;
209210 }
210211
211212 return password ;
@@ -332,7 +333,7 @@ export class DefaultReporter implements Reporter {
332333 ctx . log ( 'Sudo password attempt' ) ;
333334 }
334335
335- const isValid = this . sudoPasswordSubmittedCallback ?.( result as string ) ?? false ;
336+ const isValid = await ( this . sudoPasswordSubmittedCallback ?.( result as string ) ?? Promise . resolve ( false ) ) ;
336337 if ( isValid ) {
337338 ctx . log ( 'Sudo password successful!' ) ;
338339
@@ -349,17 +350,21 @@ export class DefaultReporter implements Reporter {
349350 await this . displayProgress ( ) ;
350351 }
351352
352- private async getUserPassword ( ) : Promise < string > {
353+ private async getUserPassword ( title ?: string ) : Promise < string > {
353354 let attemptCount = 0 ;
354355
355356 while ( attemptCount < 3 ) {
356357 const passwordAttempt = await this . updateStateAndAwaitEvent < string > (
357- ( ) => this . updateRenderState ( RenderStatus . SUDO_PROMPT , { attemptCount, cancellable : false } ) ,
358+ ( ) => this . updateRenderState ( RenderStatus . SUDO_PROMPT , { attemptCount, cancellable : false , title } ) ,
358359 RenderEvent . SUDO_PROMPT_RESULT ,
359360 ) ;
360361
361362 // Validates that the password works
362- if ( SudoUtils . validate ( passwordAttempt ) ) {
363+ if ( await SudoUtils . validate ( passwordAttempt ) ) {
364+ // Drop the sudo session so it is not cached for future prompts.
365+ // The inline sudo path (handleInlineSudoPassword) caches intentionally;
366+ // this path (promptSudo) must not.
367+ await SudoUtils . invalidate ( ) ;
363368 await this . displayProgress ( ) ;
364369 return passwordAttempt ;
365370 }
0 commit comments