@@ -230,6 +230,46 @@ func TestValidateBrowserURL(t *testing.T) {
230230 }
231231}
232232
233+ // TestValidateBrowserURL_WindowsRundll32Escape tests that validateBrowserURL blocks
234+ // payloads that could abuse the Windows "rundll32 url.dll,OpenURL" browser opener
235+ // (LOLBAS T1218.011). If any of these cases pass validation, an attacker-controlled
236+ // URL could execute arbitrary files via rundll32.
237+ // Reference: https://lolbas-project.github.io/lolbas/Libraries/Url/
238+ func TestValidateBrowserURL_WindowsRundll32Escape (t * testing.T ) {
239+ tests := []struct {
240+ name string
241+ url string
242+ }{
243+ // url.dll OpenURL can launch .hta payloads via mshta.exe
244+ {name : "hta via file protocol" , url : "file:///C:/Temp/payload.hta" },
245+ // url.dll OpenURL can launch executables from .url shortcut files
246+ {name : "url shortcut file" , url : "file:///C:/Temp/launcher.url" },
247+ // url.dll OpenURL / FileProtocolHandler can run executables directly
248+ {name : "exe via file protocol" , url : "file:///C:/Windows/System32/calc.exe" },
249+ // Obfuscated file protocol handler variant
250+ {name : "obfuscated file handler" , url : "file:///C:/Temp/payload.exe" },
251+ // UNC path via file scheme to remote payload
252+ {name : "unc path file scheme" , url : "file://attacker.com/share/payload.exe" },
253+ // data: URI could be passed through to a handler
254+ {name : "data uri" , url : "data:text/html,<script>alert(1)</script>" },
255+ // vbscript scheme
256+ {name : "vbscript scheme" , url : "vbscript:Execute(\" MsgBox(1)\" )" },
257+ // about scheme
258+ {name : "about scheme" , url : "about:blank" },
259+ // ms-msdt protocol handler (Follina-style)
260+ {name : "ms-msdt handler" , url : "ms-msdt:/id PCWDiagnostic /skip force /param" },
261+ // search-ms protocol handler
262+ {name : "search-ms handler" , url : "search-ms:query=calc&crumb=location:\\ \\ attacker.com\\ share" },
263+ }
264+ for _ , tt := range tests {
265+ t .Run (tt .name , func (t * testing.T ) {
266+ if err := validateBrowserURL (tt .url ); err == nil {
267+ t .Errorf ("validateBrowserURL(%q) = nil; want error (payload must be blocked to prevent rundll32 url.dll,OpenURL abuse)" , tt .url )
268+ }
269+ })
270+ }
271+ }
272+
233273func restoreStoredOAuthLoader (t * testing.T , loader func (context.Context , string ) (* oauth.Token , error )) {
234274 t .Helper ()
235275
0 commit comments