@@ -21,7 +21,7 @@ func Enrich(pp []ListeningPort) {
2121 }
2222 if pp [i ].Type != PortTypeDocker {
2323 pp [i ].Type = ClassifyPort (pp [i ].Port )
24- pp [i ].IsApp = isDesktopApp (pp [i ].Command )
24+ pp [i ].IsApp = isDesktopApp (pp [i ].Command , pp [ i ]. Process , pp [ i ]. PID )
2525 }
2626 }
2727}
@@ -276,8 +276,14 @@ func collectPIDs(pp []ListeningPort) []int {
276276 return pids
277277}
278278
279- // isDesktopApp detects if the command belongs to a desktop application.
280- func isDesktopApp (command string ) bool {
279+ // isDesktopApp detects if the command belongs to a desktop application or
280+ // OS-level system service that is not relevant to development.
281+ func isDesktopApp (command string , process string , pid int ) bool {
282+ if runtime .GOOS == "windows" {
283+ return isWindowsDesktopApp (command , process , pid )
284+ }
285+
286+ // macOS / Linux
281287 if command == "" {
282288 return false
283289 }
@@ -290,6 +296,59 @@ func isDesktopApp(command string) bool {
290296 return false
291297}
292298
299+ // isWindowsDesktopApp detects Windows desktop apps and system services.
300+ // PID 0 (System Idle) and PID 4 (System) own ports like 135, 139, 445.
301+ func isWindowsDesktopApp (command string , process string , pid int ) bool {
302+ if pid == 0 || pid == 4 {
303+ return true
304+ }
305+
306+ lower := strings .ToLower (command )
307+ if lower == "" {
308+ lower = strings .ToLower (process )
309+ }
310+ if lower == "" {
311+ // No command or process name — system service not visible without elevation
312+ return true
313+ }
314+
315+ // Windows system services
316+ if strings .Contains (lower , `\windows\` ) {
317+ return true
318+ }
319+ // User-installed desktop apps (AppData\Local houses Discord, Cursor, Slack, etc.)
320+ if strings .Contains (lower , `\appdata\` ) {
321+ return true
322+ }
323+ // Microsoft Store apps
324+ if strings .Contains (lower , `\windowsapps\` ) {
325+ return true
326+ }
327+ // Known desktop app executable names (for cases where only the process name is available)
328+ knownApps := []string {
329+ "discord" , "cursor" , "slack" , "spotify" , "figma" , "zoom" ,
330+ "teams" , "onedrive" , "dropbox" , "githubdesktop" , "notion" ,
331+ "telegram" , "whatsapp" , "1password" , "bitwarden" ,
332+ "chrome" , "firefox" , "msedge" , "brave" , "opera" ,
333+ "explorer" , "searchhost" , "widgets" ,
334+ }
335+ // Extract the base executable name without .exe
336+ baseName := strings .ToLower (process )
337+ if i := strings .LastIndex (baseName , `\` ); i >= 0 {
338+ baseName = baseName [i + 1 :]
339+ }
340+ baseName = strings .TrimSuffix (baseName , ".exe" )
341+ // Also strip any trailing quote artifacts from netstat parsing
342+ baseName = strings .TrimRight (baseName , `"` )
343+
344+ for _ , app := range knownApps {
345+ if strings .Contains (baseName , app ) {
346+ return true
347+ }
348+ }
349+ return false
350+ }
351+
293352// ClassifyPort returns PortTypeSystem for well-known ports (<1024), else PortTypeUser.
294353func ClassifyPort (port int ) PortType {
295354 if port < 1024 {
0 commit comments