Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .Jules/sentinel.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
**Vulnerability:** The app allowed opening any URL string without validating the scheme, making it possible for attackers to use NSWorkspace.shared.open with potentially dangerous handlers like file:// or system preference handlers.
**Learning:** Passing untrusted URLs to NSWorkspace.shared.open or /usr/bin/open acts similarly to a shell execution if non-standard or local file schemes are used. It bypasses normal app boundaries.
**Prevention:** Always restrict URL schemes to an explicit allowlist (like http, https) before delegating to system URL openers.
## 2026-06-16 - [Dangerous URL Scheme execution in automation frameworks]
**Vulnerability:** Although an explicit scheme allowlist is the strongest defense, applying it blindly to a customizable automation framework (like `TriggerKit`) broke critical user functionality relying on standard custom schemes (like `shortcuts://` or `mailto:`). This forced us to roll back a naive allowlist.
**Learning:** In contexts like scripting or macro execution where flexibility is a core requirement, an allowlist can cause severe functional regressions. We must fallback to an explicit blocklist of definitively dangerous system schemes (e.g. `file`, `x-apple.systempreferences`) to mitigate the `NSWorkspace.shared.open` sandbox escape vector without breaking valid user automations.
**Prevention:** Consider the product requirements before applying restrictive allowlists. Use a blocklist targeting known unsafe execution vectors (file://, system preferences) for generalized scripting engines where an allowlist isn't feasible.
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ private extension AutomationStep {
if let allowedSchemes, !allowedSchemes.contains(scheme) {
return [issue(disallowedCode, index: index, message: "\(label) scheme is not allowed: \(scheme)")]
}

// Security: Block dangerous URL schemes that can bypass app sandboxing or manipulate system settings.
let blockedSchemes: Set<String> = ["file", "x-apple.systempreferences"]
if blockedSchemes.contains(scheme) {
return [issue(disallowedCode, index: index, message: "\(label) scheme is dangerously blocked: \(scheme)")]
}

return []
}

Expand Down
8 changes: 8 additions & 0 deletions TriggerKit/Sources/TriggerKitRuntime/AutomationExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,14 @@ public final class AutomationExecutor {
if let allowedSchemes, !allowedSchemes.contains(scheme) {
return .failure("URL scheme not allowed: \(scheme)")
}

// Security: Block dangerous URL schemes that can bypass app sandboxing or manipulate system settings.
// These schemes act similarly to shell execution if passed untrusted inputs.
let blockedSchemes: Set<String> = ["file", "x-apple.systempreferences"]
if blockedSchemes.contains(scheme) {
return .failure("Dangerous URL scheme blocked: \(scheme)")
}

guard NSWorkspace.shared.open(url) else {
return .failure("Could not open URL: \(urlString)")
}
Expand Down
Loading