Skip to content

Commit 855a607

Browse files
committed
fix(computer-use): protect terminals, match protected bundle IDs case-insensitively, and remember unlisted app names
1 parent dd01573 commit 855a607

5 files changed

Lines changed: 27 additions & 16 deletions

File tree

‎apps/desktop/README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ group with the **Computer Use** restriction. Older desktop builds omit this opti
240240
continue to work.
241241

242242
The user grants Accessibility and Screen Recording through macOS; every app is then available except
243-
Sim, System Settings and password managers, which the helper refuses. With **Ask before using a new
243+
Sim, System Settings, password managers and terminals (shell access has its own Terminal control),
244+
which the helper refuses. With **Ask before using a new
244245
app** on, each app's first use is approved for the task or persistently, and persistent approvals are
245246
listed in Settings and can be revoked. Sign-out and deployment changes clear opt-in, the ask choice
246247
and approvals. The conversation shows the

‎apps/desktop/native/computer-use/ComputerUse.swift‎

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,15 +142,21 @@ func elementRect(_ element: AXUIElement) -> CGRect? {
142142
AXValueGetValue(unsafeBitCast(rawSize, to: AXValue.self), .cgSize, &size) else { return nil }
143143
return CGRect(origin: position, size: size)
144144
}
145-
/// Apps computer use never operates: macOS security settings and password managers.
145+
/// Apps computer use never operates, lowercased: macOS security settings, password managers, and
146+
/// terminals, whose shell access has its own Terminal control.
146147
let PROTECTED_APPS: Set<String> = [
147-
"com.apple.systempreferences", "com.apple.keychainaccess", "com.apple.Passwords",
148-
"com.1password.1password", "com.agilebits.onepassword7", "com.bitwarden.desktop", "org.keepassxc.keepassxc",
148+
"com.apple.systempreferences", "com.apple.keychainaccess", "com.apple.passwords",
149+
"com.1password.1password", "com.agilebits.onepassword7", "com.agilebits.onepassword-osx", "com.bitwarden.desktop",
150+
"org.keepassxc.keepassxc", "com.lastpass.lastpass", "in.sinew.enpass-desktop", "me.proton.pass.electron",
151+
"com.markmcguill.strongbox", "com.markmcguill.strongbox.mac",
152+
"com.apple.terminal", "com.googlecode.iterm2", "dev.warp.warp-stable", "com.mitchellh.ghostty",
149153
]
150154
func appFor(_ bundleId: String?, launch: Bool = false) async throws -> NSRunningApplication {
151155
let bundle = try required(bundleId, "bundleId")
152-
guard bundle != Bundle.main.bundleIdentifier, !bundle.hasPrefix("com.simstudio."), !bundle.hasPrefix("ai.sim.desktop"), !PROTECTED_APPS.contains(bundle) else {
153-
throw ComputerError("protected_app", "Computer use does not operate Sim, System Settings, or password managers.")
156+
// Bundle identifiers match case-insensitively in Launch Services.
157+
let key = bundle.lowercased()
158+
guard key != Bundle.main.bundleIdentifier?.lowercased(), !key.hasPrefix("com.simstudio."), !key.hasPrefix("ai.sim.desktop"), !PROTECTED_APPS.contains(key) else {
159+
throw ComputerError("protected_app", "Computer use does not operate Sim, System Settings, password managers, or terminals; use the terminal tool for shell work.")
154160
}
155161
var apps = NSRunningApplication.runningApplications(withBundleIdentifier: bundle).filter { !$0.isTerminated }
156162
if apps.isEmpty && launch {

‎apps/desktop/src/main/computer-use/service.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export class ComputerUseService {
144144

145145
reset(): void {
146146
this.cancel()
147+
this.appNames.clear()
147148
this.deps.config.set('computerUseEnabled', false)
148149
this.deps.config.set('computerUseAskForApps', false)
149150
this.deps.config.set('computerUseAllowedApps', [])
@@ -397,6 +398,8 @@ export class ComputerUseService {
397398
this.appNames.clear()
398399
for (const app of apps.apps) this.appNames.set(app.bundleId, app.name)
399400
}
401+
/** An app outside the scanned folders keeps its bundle ID, so it is not rescanned on every action. */
402+
if (!this.appNames.has(bundleId)) this.appNames.set(bundleId, bundleId)
400403
return this.appNames.get(bundleId) ?? bundleId
401404
}
402405
}

‎apps/docs/content/docs/desktop/index.mdx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,13 @@ To enable it when available:
9898
1. Turn **Use apps on this Mac** to **On**.
9999
2. Select **Allow** next to **Accessibility** (app interaction) and **Screen Recording** (screenshots), grant them in System Settings, then return to Sim.
100100

101-
Sim can then use any app except password managers and macOS System Settings. To approve each app the first time Sim uses it, turn on **Ask before using a new app**; Sim then offers **Allow for This Task**, **Always Allow**, or **Cancel**.
101+
Sim can then use any app except terminals, password managers, and macOS System Settings; shell work goes through **Terminal** access instead. To approve each app the first time Sim uses it, turn on **Ask before using a new app**; Sim then offers **Allow for This Task**, **Always Allow**, or **Cancel**.
102102

103103
Sim can read app windows and interact through clicks, text, keyboard shortcuts, scrolling, and supported accessibility controls. Screenshots and returned app content can be sent to your Sim deployment and model. Some actions require bringing the app to the foreground; app compatibility and macOS permissions can still limit what succeeds.
104104

105105
The conversation shows the active app and action. Select **Stop**, or press **Cmd + Shift + Escape** when that shortcut is available, to cancel active and queued computer actions. Stopping cannot undo input already delivered to an app. Verify the app's current state before repeating an interrupted action.
106106

107-
With **Ask before using a new app** on, use **Revoke** under **Approved apps** to remove a saved approval. Signing out or changing deployments clears the device opt-in and app approvals. Computer Use never operates Sim, macOS System Settings, or password managers.
107+
With **Ask before using a new app** on, use **Revoke** under **Approved apps** to remove a saved approval. Signing out or changing deployments clears the device opt-in and app approvals. Computer Use never operates Sim, macOS System Settings, password managers, or terminals.
108108

109109
### Terminal access
110110

‎apps/sim/app/workspace/[workspaceId]/settings/components/desktop/computer-use.tsx‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import { SettingsSection } from '@/app/workspace/[workspaceId]/settings/componen
1111
import { useUserPermissionConfig } from '@/ee/access-control/hooks/permission-groups'
1212
import { useComputerUseStatus } from '@/hooks/use-computer-use-status'
1313

14+
const ON_OFF_OPTIONS = [
15+
{ value: 'off', label: 'Off' },
16+
{ value: 'on', label: 'On' },
17+
]
18+
1419
/** The activity stays visible so an in-flight action can be stopped; the device controls need the permission group's consent. */
1520
export function ComputerUseSettings() {
1621
const { workspaceId } = useParams<{ workspaceId: string }>()
@@ -60,10 +65,6 @@ function ComputerUseSettingsControls() {
6065
setPending(false)
6166
}
6267
}
63-
const onOff = [
64-
{ value: 'off', label: 'Off' },
65-
{ value: 'on', label: 'On' },
66-
]
6768
const askForApps = status?.askForApps
6869
const setAskForApps = bridge.setAskForApps
6970
return (
@@ -75,7 +76,7 @@ function ComputerUseSettingsControls() {
7576
</Label>
7677
<ChipSwitch
7778
aria-label='Use apps on this Mac'
78-
options={onOff}
79+
options={ON_OFF_OPTIONS}
7980
value={status?.enabled ? 'on' : 'off'}
8081
disabled={pending || !status}
8182
onChange={(value) =>
@@ -84,11 +85,11 @@ function ComputerUseSettingsControls() {
8485
/>
8586
</div>
8687
<p className='text-[var(--text-muted)] text-sm'>
87-
Works in any app except password managers and System Settings.
88+
Sim can use any app except terminals, password managers, and System Settings.
8889
</p>
8990
{error && (
9091
<div className='flex items-center justify-between text-sm'>
91-
<span>Couldn't reach the computer use helper.</span>
92+
<span>Could not reach the Computer Use helper.</span>
9293
<Chip onClick={() => void refresh()}>Retry</Chip>
9394
</div>
9495
)}
@@ -124,7 +125,7 @@ function ComputerUseSettingsControls() {
124125
</Label>
125126
<ChipSwitch
126127
aria-label='Ask before using a new app'
127-
options={onOff}
128+
options={ON_OFF_OPTIONS}
128129
value={askForApps ? 'on' : 'off'}
129130
disabled={pending}
130131
onChange={(value) =>

0 commit comments

Comments
 (0)