5
5
6
6
import './media/extensionsViewlet.css' ;
7
7
import { localize , localize2 } from '../../../../nls.js' ;
8
- import { Delayer } from '../../../../base/common/async.js' ;
8
+ import { timeout , Delayer , Promises } from '../../../../base/common/async.js' ;
9
9
import { isCancellationError } from '../../../../base/common/errors.js' ;
10
10
import { createErrorWithActions } from '../../../../base/common/errorMessage.js' ;
11
11
import { IWorkbenchContribution } from '../../../common/contributions.js' ;
@@ -18,6 +18,7 @@ import { IInstantiationService, ServicesAccessor } from '../../../../platform/in
18
18
import { IExtensionService } from '../../../services/extensions/common/extensions.js' ;
19
19
import { IExtensionsWorkbenchService , IExtensionsViewPaneContainer , VIEWLET_ID , CloseExtensionDetailsOnViewChangeKey , INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID , WORKSPACE_RECOMMENDATIONS_VIEW_ID , AutoCheckUpdatesConfigurationKey , OUTDATED_EXTENSIONS_VIEW_ID , CONTEXT_HAS_GALLERY , extensionsSearchActionsMenu , AutoRestartConfigurationKey } from '../common/extensions.js' ;
20
20
import { InstallLocalExtensionsInRemoteAction , InstallRemoteExtensionsInLocalAction } from './extensionsActions.js' ;
21
+ import { IExtensionManagementService } from '../../../../platform/extensionManagement/common/extensionManagement.js' ;
21
22
import { IWorkbenchExtensionEnablementService , IExtensionManagementServerService , IExtensionManagementServer } from '../../../services/extensionManagement/common/extensionManagement.js' ;
22
23
import { ExtensionsInput } from '../common/extensionsInput.js' ;
23
24
import { ExtensionsListView , EnabledExtensionsView , DisabledExtensionsView , RecommendedExtensionsView , WorkspaceRecommendedExtensionsView , ServerInstalledExtensionsView , DefaultRecommendedExtensionsView , UntrustedWorkspaceUnsupportedExtensionsView , UntrustedWorkspacePartiallySupportedExtensionsView , VirtualWorkspaceUnsupportedExtensionsView , VirtualWorkspacePartiallySupportedExtensionsView , DefaultPopularExtensionsView , DeprecatedExtensionsView , SearchMarketplaceExtensionsView , RecentlyUpdatedExtensionsView , OutdatedExtensionsView , StaticQueryExtensionsView , NONE_CATEGORY } from './extensionsViews.js' ;
@@ -33,20 +34,22 @@ import { IWorkspaceContextService } from '../../../../platform/workspace/common/
33
34
import { IContextKeyService , ContextKeyExpr , RawContextKey , IContextKey } from '../../../../platform/contextkey/common/contextkey.js' ;
34
35
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js' ;
35
36
import { ILogService } from '../../../../platform/log/common/log.js' ;
36
- import { INotificationService } from '../../../../platform/notification/common/notification.js' ;
37
+ import { INotificationService , NotificationPriority } from '../../../../platform/notification/common/notification.js' ;
38
+ import { IHostService } from '../../../services/host/browser/host.js' ;
37
39
import { IWorkbenchLayoutService } from '../../../services/layout/browser/layoutService.js' ;
38
40
import { ViewPaneContainer } from '../../../browser/parts/views/viewPaneContainer.js' ;
39
41
import { ViewPane } from '../../../browser/parts/views/viewPane.js' ;
40
42
import { Query } from '../common/extensionQuery.js' ;
41
43
import { SuggestEnabledInput } from '../../codeEditor/browser/suggestEnabledInput/suggestEnabledInput.js' ;
42
44
import { alert } from '../../../../base/browser/ui/aria/aria.js' ;
43
- import { EXTENSION_CATEGORIES } from '../../../../platform/extensions/common/extensions.js' ;
45
+ import { EXTENSION_CATEGORIES , ExtensionType } from '../../../../platform/extensions/common/extensions.js' ;
44
46
import { Registry } from '../../../../platform/registry/common/platform.js' ;
45
47
import { ILabelService } from '../../../../platform/label/common/label.js' ;
46
48
import { MementoObject } from '../../../common/memento.js' ;
47
49
import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js' ;
48
50
import { IPreferencesService } from '../../../services/preferences/common/preferences.js' ;
49
51
import { SIDE_BAR_DRAG_AND_DROP_BACKGROUND } from '../../../common/theme.js' ;
52
+ import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js' ;
50
53
import { VirtualWorkspaceContext , WorkbenchStateContext } from '../../../common/contextkeys.js' ;
51
54
import { ICommandService } from '../../../../platform/commands/common/commands.js' ;
52
55
import { installLocalInRemoteIcon } from './extensionsIcons.js' ;
@@ -56,6 +59,7 @@ import { IPaneCompositePartService } from '../../../services/panecomposite/brows
56
59
import { coalesce } from '../../../../base/common/arrays.js' ;
57
60
import { extractEditorsAndFilesDropData } from '../../../../platform/dnd/browser/dnd.js' ;
58
61
import { extname } from '../../../../base/common/resources.js' ;
62
+ import { isMalicious } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js' ;
59
63
import { ILocalizedString } from '../../../../platform/action/common/action.js' ;
60
64
import { registerNavigableContainer } from '../../../browser/actions/widgetNavigationCommands.js' ;
61
65
import { MenuWorkbenchToolBar } from '../../../../platform/actions/browser/toolbar.js' ;
@@ -963,3 +967,52 @@ export class StatusUpdater extends Disposable implements IWorkbenchContribution
963
967
}
964
968
}
965
969
}
970
+
971
+ export class MaliciousExtensionChecker implements IWorkbenchContribution {
972
+
973
+ constructor (
974
+ @IExtensionManagementService private readonly extensionsManagementService : IExtensionManagementService ,
975
+ @IHostService private readonly hostService : IHostService ,
976
+ @ILogService private readonly logService : ILogService ,
977
+ @INotificationService private readonly notificationService : INotificationService ,
978
+ @IWorkbenchEnvironmentService private readonly environmentService : IWorkbenchEnvironmentService
979
+ ) {
980
+ if ( ! this . environmentService . disableExtensions ) {
981
+ this . loopCheckForMaliciousExtensions ( ) ;
982
+ }
983
+ }
984
+
985
+ private loopCheckForMaliciousExtensions ( ) : void {
986
+ this . checkForMaliciousExtensions ( )
987
+ . then ( ( ) => timeout ( 1000 * 60 * 5 ) ) // every five minutes
988
+ . then ( ( ) => this . loopCheckForMaliciousExtensions ( ) ) ;
989
+ }
990
+
991
+ private checkForMaliciousExtensions ( ) : Promise < void > {
992
+ return this . extensionsManagementService . getExtensionsControlManifest ( ) . then ( extensionsControlManifest => {
993
+
994
+ return this . extensionsManagementService . getInstalled ( ExtensionType . User ) . then ( installed => {
995
+ const maliciousExtensions = installed . filter ( e => isMalicious ( e . identifier , extensionsControlManifest ) ) ;
996
+
997
+ if ( maliciousExtensions . length ) {
998
+ return Promises . settled ( maliciousExtensions . map ( e => this . extensionsManagementService . uninstall ( e ) . then ( ( ) => {
999
+ this . notificationService . prompt (
1000
+ Severity . Warning ,
1001
+ localize ( 'malicious warning' , "We have uninstalled '{0}' which was reported to be problematic." , e . identifier . id ) ,
1002
+ [ {
1003
+ label : localize ( 'reloadNow' , "Reload Now" ) ,
1004
+ run : ( ) => this . hostService . reload ( )
1005
+ } ] ,
1006
+ {
1007
+ sticky : true ,
1008
+ priority : NotificationPriority . URGENT
1009
+ }
1010
+ ) ;
1011
+ } ) ) ) ;
1012
+ } else {
1013
+ return Promise . resolve ( undefined ) ;
1014
+ }
1015
+ } ) . then ( ( ) => undefined ) ;
1016
+ } , err => this . logService . error ( err ) ) ;
1017
+ }
1018
+ }
0 commit comments