You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Adopt ShellKit's PathMapping: authorizePath must return the translated host path (SwiftBash#83 follow-up) #6
Cocoanetics/SwiftBash#83 moved the sandbox's virtual↔host path mapping into ShellKit (PathMapping, carried as Sandbox.pathMapping, landed in Cocoanetics/ShellKit#17). Shell.resolve(_:) now translates script-visible virtual paths (e.g. /tmp/x, /batch/x under swift-bash exec --sandbox) to the host directories that back them, and Sandbox.confined(to:) authorizes exactly that host space. SwiftPorts and SwiftBash's JS runtime are adapted (Cocoanetics/SwiftBash#88, Cocoanetics/SwiftPorts#64).
SwiftScript is not yet adapted: authorizePath (Sources/SwiftScriptInterpreter/API/HostHooks.swift) gates the literal path and the bridges then do Foundation I/O on that same literal. Under a path-mapped sandbox every virtual absolute path is therefore denied — fail-closed, safe, but FS access for SwiftScript scripts inside the SwiftBash sandbox stays limited.
The invariant that shapes the fix
Translating for the check but not the I/O (or vice versa) is an escape: authorize(translate("/tmp/x")) passes against the per-instance temp dir while FileManager would then touch the host's shared/tmp/x. The translated path must be the one the Foundation call consumes. Half-adopting is worse than not adopting — this ships whole or not at all.
Proposed change
authorizePath(_:for:) (String and URL overloads) resolves first — ShellKit.Shell.current.resolve(path) (which also anchors relative paths to the shell's virtual CWD instead of the host process CWD) — authorizes the host form, and returns it.
BridgeGeneratorTool (Sources/BridgeGeneratorTool/main.swift, gate emission around line 1117): fs-gated args bind as var, and the emission becomes arg0 = try await authorizePath(arg0, for: .read) so the Foundation call consumes the translated path. Network gates stay Void.
Regenerate via Tools/regen-foundation-bridge.sh — NB: regeneration on a current machine produces ~2k lines of unrelated symbol-graph drift (newer SDK than the committed extract; verified 2026-06-11). Refresh the extract in a separate commit first, or pin the regen environment, so the semantic diff stays reviewable.
Hand-written sites consume the return too: Interpreter+FileIO.swift, the hand-rolled String/Data bridges.
Display stays virtual: FileManager.currentDirectoryPath already reports the virtual CWD; FileManager.temporaryDirectory should report ShellKit.Shell.temporaryDirectory (sandbox-aware) rather than the host's shared temp root; anything echoing resolved paths folds through Shell.displayPath(for:).
Tests: mirror SwiftBash's ConfinedSandboxTests — a .confined sandbox over a PathMapping, script writes /tmp/x + relative paths, bytes land in the mapped host dirs, denials outside, no host path in script-visible output.
Until this lands, SwiftScript-in-sandbox keeps the post-SwiftBash#82 interim contract (virtual spellings denied, fail-closed).
Activity