//go:build darwin package blocker import ( "fmt" "log" "os" "os/exec" "path/filepath" "strings" ) var systemAllowed = map[string]bool{ "finder": true, "terminal": true, "iterm": true, "iterm2": true, "bash": true, "zsh": true, "sh": true, "wails": true, "code": true, "cursor": true, "windsurf": true, "goland": true, "idea": true, "clion": true, "webstorm": true, "pycharm": true, "rider": true, "studio": true, "eclipse": true, "sublime_text": true, "git": true, "docker": true, "system events": true, "osascript": true, "client": true, "simple_care_v1.0": true, } func getVisibleProcesses() (map[uint32]string, error) { script := `tell application "System Events" set nameList to name of every process whose visible is true set pidList to unix id of every process whose visible is true set out to "" repeat with i from 1 to count of nameList set out to out & item i of nameList & ":" & item i of pidList & "\n" end repeat return out end tell` cmd := exec.Command("osascript", "-e", script) out, err := cmd.Output() if err != nil { return nil, err } procs := make(map[uint32]string) lines := strings.Split(string(out), "\n") for _, line := range lines { line = strings.TrimSpace(line) if line == "" { continue } idx := strings.LastIndex(line, ":") if idx == -1 { continue } pName := line[:idx] pIdStr := line[idx+1:] var pid uint32 if _, err := fmt.Sscanf(pIdStr, "%d", &pid); err == nil { procs[pid] = pName } } return procs, nil } func (b *Blocker) checkAndKill() { b.mu.Lock() keywords := make([]string, len(b.allowedKeywords)) copy(keywords, b.allowedKeywords) b.mu.Unlock() if len(keywords) == 0 { return } currentExec := "" if execPath, err := os.Executable(); err == nil { currentExec = strings.ToLower(filepath.Base(execPath)) } procs, err := getVisibleProcesses() if err != nil { log.Printf("[BLOCKER] Failed to get visible processes: %v", err) return } myPid := uint32(os.Getpid()) for pid, name := range procs { pNameLower := strings.ToLower(name) // 1. Always allow our app, system/critical developer tools, or agent helpers if pid == myPid || (currentExec != "" && pNameLower == currentExec) || systemAllowed[pNameLower] || strings.Contains(pNameLower, "antigravity") { continue } // 2. Check if the process name contains any allowed keywords allowed := false for _, kw := range keywords { if matchesAllowedKeyword(kw, pNameLower, pNameLower) { allowed = true break } } // 3. If not allowed, kill the application if !allowed { if b.OnBlocked != nil { b.OnBlocked(name, name) } log.Printf("[BLOCKER] KILLED unauthorized application: %s (PID: %d)", name, pid) proc, err := os.FindProcess(int(pid)) if err == nil { errKill := proc.Kill() if errKill == nil && b.OnKill != nil { b.OnKill(name, name) } } } } }