@@ -34,6 +34,11 @@ public sealed partial class BrowserControl : Microsoft.UI.Xaml.Controls.UserCont
3434
3535 private Color ? _originalBackgroundColor ;
3636
37+ /// <summary>
38+ /// URI of the current source being previewed (for resource filtering)
39+ /// </summary>
40+ private Uri ? _currentSourceUri ;
41+
3742 public delegate void NavigationCompletedHandler ( WebView2 ? sender , CoreWebView2NavigationCompletedEventArgs ? args ) ;
3843
3944 public delegate void DOMContentLoadedHandler ( CoreWebView2 ? sender , CoreWebView2DOMContentLoadedEventArgs ? args ) ;
@@ -97,6 +102,7 @@ public BrowserControl()
97102 {
98103 this . InitializeComponent ( ) ;
99104 Environment . SetEnvironmentVariable ( "WEBVIEW2_USER_DATA_FOLDER" , TempFolderPath . Path , EnvironmentVariableTarget . Process ) ;
105+ Environment . SetEnvironmentVariable ( "WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS" , "--block-new-web-contents" , EnvironmentVariableTarget . Process ) ;
100106 }
101107
102108 public void Dispose ( )
@@ -105,6 +111,7 @@ public void Dispose()
105111 {
106112 PreviewBrowser . CoreWebView2 . DOMContentLoaded -= CoreWebView2_DOMContentLoaded ;
107113 PreviewBrowser . CoreWebView2 . ContextMenuRequested -= CoreWebView2_ContextMenuRequested ;
114+ RemoveResourceFilter ( ) ;
108115 }
109116 }
110117
@@ -123,6 +130,14 @@ public void Navigate()
123130 {
124131 /* CoreWebView2.Navigate() will always trigger a navigation even if the content/URI is the same.
125132 * Use WebView2.Source to avoid re-navigating to the same content. */
133+ _currentSourceUri = Source ;
134+
135+ // Only apply resource filter for non-dev files
136+ if ( ! IsDevFilePreview )
137+ {
138+ ApplyResourceFilter ( ) ;
139+ }
140+
126141 PreviewBrowser . CoreWebView2 . Navigate ( Source . ToString ( ) ) ;
127142 }
128143 }
@@ -146,10 +161,14 @@ private void OnIsDevFilePreviewChanged()
146161 if ( IsDevFilePreview )
147162 {
148163 PreviewBrowser . CoreWebView2 . SetVirtualHostNameToFolderMapping ( Microsoft . PowerToys . FilePreviewCommon . MonacoHelper . VirtualHostName , Microsoft . PowerToys . FilePreviewCommon . MonacoHelper . MonacoDirectory , CoreWebView2HostResourceAccessKind . Allow ) ;
164+
165+ // Remove resource filter for dev files (Monaco needs to load resources)
166+ RemoveResourceFilter ( ) ;
149167 }
150168 else
151169 {
152170 PreviewBrowser . CoreWebView2 . ClearVirtualHostNameToFolderMapping ( Microsoft . PowerToys . FilePreviewCommon . MonacoHelper . VirtualHostName ) ;
171+ ApplyResourceFilter ( ) ;
153172 }
154173 }
155174 }
@@ -283,6 +302,34 @@ private void CoreWebView2_ContextMenuRequested(CoreWebView2 sender, CoreWebView2
283302 }
284303 }
285304
305+ /// <summary>
306+ /// Applies strict resource filtering for non-dev files to block external resources.
307+ /// This prevents XSS attacks and unwanted external content loading.
308+ /// </summary>
309+ private void ApplyResourceFilter ( )
310+ {
311+ // Remove existing handler to prevent duplicate subscriptions
312+ RemoveResourceFilter ( ) ;
313+
314+ // Add filter and subscribe to resource requests
315+ PreviewBrowser . CoreWebView2 . AddWebResourceRequestedFilter ( "*" , CoreWebView2WebResourceContext . All ) ;
316+ PreviewBrowser . CoreWebView2 . WebResourceRequested += CoreWebView2_WebResourceRequested ;
317+ }
318+
319+ private void RemoveResourceFilter ( )
320+ {
321+ PreviewBrowser . CoreWebView2 . WebResourceRequested -= CoreWebView2_WebResourceRequested ;
322+ }
323+
324+ private void CoreWebView2_WebResourceRequested ( CoreWebView2 sender , CoreWebView2WebResourceRequestedEventArgs args )
325+ {
326+ // Only allow loading the specified source file. Block all other resources for security.
327+ if ( _currentSourceUri != null && new Uri ( args . Request . Uri ) != _currentSourceUri )
328+ {
329+ args . Response = PreviewBrowser . CoreWebView2 . Environment . CreateWebResourceResponse ( null , 403 , "Forbidden" , null ) ;
330+ }
331+ }
332+
286333 private void CoreWebView2_DOMContentLoaded ( CoreWebView2 sender , CoreWebView2DOMContentLoadedEventArgs args )
287334 {
288335 // If the file being previewed is HTML or HTM, reset the background color to its original state.
0 commit comments