@@ -98,17 +98,31 @@ export class BrowserManager {
9898 }
9999
100100 try {
101+ // Security: Check if system Keychain should be used (opt-in for security)
102+ const useSystemKeychain = process . env . HAB_USE_SYSTEM_KEYCHAIN === 'true' ;
103+
104+ const ignoreArgs = [ "--enable-automation" ] ;
105+
106+ if ( ! useSystemKeychain ) {
107+ // Default: Use isolated password store (more secure)
108+ launchArgs . push ( "--password-store=basic" ) ;
109+ console . log ( "🔒 Using isolated password store (secure mode). Set HAB_USE_SYSTEM_KEYCHAIN=true to use system Keychain." ) ;
110+ } else {
111+ // Opt-in: Allow system Keychain access
112+ ignoreArgs . push ( "--password-store=basic" , "--use-mock-keychain" ) ;
113+ console . log ( "⚠️ Using system Keychain (HAB_USE_SYSTEM_KEYCHAIN=true)" ) ;
114+ }
115+
116+ if ( loadExtensions ) {
117+ ignoreArgs . push ( "--disable-extensions" ) ;
118+ }
119+
101120 // Use launchPersistentContext for UserData persistence
102121 this . context = await chromium . launchPersistentContext ( this . session . userDataDir , {
103122 channel : this . options . channel ,
104123 headless : ! this . options . headed ,
105124 args : launchArgs ,
106- ignoreDefaultArgs : [
107- "--enable-automation" ,
108- "--password-store=basic" , // 移除这个,允许使用系统 Keychain
109- "--use-mock-keychain" , // 移除这个,允许访问真实 Keychain
110- ...( loadExtensions ? [ "--disable-extensions" ] : [ ] ) ,
111- ] ,
125+ ignoreDefaultArgs : ignoreArgs ,
112126 viewport : { width : 1280 , height : 720 } ,
113127 } ) ;
114128
@@ -137,6 +151,42 @@ export class BrowserManager {
137151 }
138152 }
139153
154+ // Security: Whitelist of trusted extension IDs
155+ // Users can add their trusted extensions here
156+ private ALLOWED_EXTENSION_IDS = new Set < string > ( [
157+ // Example: MetaMask
158+ // 'nkbihfbeogaeaoehlefnkodbefgpgknn',
159+ // Add your trusted extensions here
160+ ] ) ;
161+
162+ // Security: Check if extension manifest contains dangerous permissions
163+ private isExtensionSafe ( manifestPath : string ) : boolean {
164+ try {
165+ const { readFileSync } = require ( 'node:fs' ) ;
166+ const manifest = JSON . parse ( readFileSync ( manifestPath , 'utf-8' ) ) ;
167+
168+ // Check for dangerous permissions
169+ const dangerousPerms = [ 'debugger' , 'webRequest' , 'proxy' , '<all_urls>' , 'webRequestBlocking' ] ;
170+ const permissions = [
171+ ...( manifest . permissions || [ ] ) ,
172+ ...( manifest . host_permissions || [ ] ) ,
173+ ...( manifest . optional_permissions || [ ] )
174+ ] ;
175+
176+ for ( const perm of dangerousPerms ) {
177+ if ( permissions . includes ( perm ) ) {
178+ console . log ( `⚠️ Extension blocked: contains dangerous permission '${ perm } '` ) ;
179+ return false ;
180+ }
181+ }
182+
183+ return true ;
184+ } catch ( error ) {
185+ console . log ( `⚠️ Failed to validate extension manifest: ${ error } ` ) ;
186+ return false ;
187+ }
188+ }
189+
140190 private loadChromeExtensions ( ) : string [ ] {
141191 const extensionPaths : string [ ] = [ ] ;
142192
@@ -159,6 +209,12 @@ export class BrowserManager {
159209 // Skip hidden files and .DS_Store
160210 if ( extensionId . startsWith ( '.' ) ) continue ;
161211
212+ // Security: Whitelist check (if whitelist is not empty, enforce it)
213+ if ( this . ALLOWED_EXTENSION_IDS . size > 0 && ! this . ALLOWED_EXTENSION_IDS . has ( extensionId ) ) {
214+ console . log ( `⚠️ Extension ${ extensionId } not in whitelist, skipping` ) ;
215+ continue ;
216+ }
217+
162218 const extensionDir = join ( chromeExtensionsDir , extensionId ) ;
163219
164220 try {
@@ -180,7 +236,14 @@ export class BrowserManager {
180236 // Verify the extension path exists and has manifest
181237 const manifestPath = join ( extensionPath , 'manifest.json' ) ;
182238 if ( existsSync ( manifestPath ) ) {
239+ // Security: Validate extension safety
240+ if ( ! this . isExtensionSafe ( manifestPath ) ) {
241+ console . log ( `⚠️ Extension ${ extensionId } blocked due to dangerous permissions` ) ;
242+ continue ;
243+ }
244+
183245 extensionPaths . push ( extensionPath ) ;
246+ console . log ( `✅ Loaded safe extension: ${ extensionId } ` ) ;
184247 }
185248 } catch ( error ) {
186249 // Skip invalid extension directories
@@ -189,15 +252,7 @@ export class BrowserManager {
189252 }
190253 }
191254
192- console . log ( `Found ${ extensionPaths . length } valid Chrome extensions to load` ) ;
193-
194- // Log first few extension paths for debugging
195- if ( extensionPaths . length > 0 ) {
196- console . log ( `Sample extension paths (first 3):` ) ;
197- extensionPaths . slice ( 0 , 3 ) . forEach ( path => {
198- console . log ( ` - ${ path } ` ) ;
199- } ) ;
200- }
255+ console . log ( `Found ${ extensionPaths . length } valid and safe Chrome extensions to load` ) ;
201256 } catch ( error ) {
202257 console . error ( "Error loading Chrome extensions:" , error ) ;
203258 }
0 commit comments