An AI cannot be trusted to keep itself safe. This is a design constraint for any system that lets a model act.
Prompts can encourage caution around destructive commands like file writes or instructions found in tool output. Their effect depends on the model continuing to interpret the situation correctly, while the underlying authority remains available. myPAL puts the durable boundary below the model.
A tool call enters the harness as a proposal. Before execution, myPAL checks that the capability exists, resolves the arguments to a specific operation, applies the captured policy, and verifies the request's authority. Every step is owned by code outside the model response.
Authority is fixed before the run
myPAL builds an immutable capability snapshot for each run. It contains the schemas shown to the model, the validated operation registry, and the executable routes retained by the harness. That snapshot fixes the available surface for the life of the run.
A read-only workspace contains read, list, and search capabilities. Write, edit, and shell routes are absent.
An invented call resolves to TOOL_UNAVAILABLE, even when its name and arguments look valid. Full workspace profiles deliberately add mutation and shell adapters; memory, web, media, and MCP routes enter through the same builder before capture. Once captured, the model has no route for registering another executor or replacing an existing one.
flowchart LR
Model[Model proposes a tool call] --> Registry{Capability exists?}
Registry -- no --> Unavailable[Reject as unavailable]
Registry -- yes --> Classifier[Resolve exact operation]
Classifier --> Policy{Policy decision}
Policy -- deny --> Denied[Reject]
Policy -- ask --> Approval{Exact approval received?}
Approval -- no or expired --> Denied
Approval -- yes --> Authorized[Authorized invocation]
Policy -- allow --> Authorized
Authorized --> Adapter[Bound tool adapter]
Adapter --> Boundary[Filesystem, process, or service boundary]
Policy follows the operation
Tool names are too broad for useful safety decisions. One shell interface covers tests, network access, and potentially destructive commands, so myPAL classifies the supplied arguments into an operation with a declared side effect. Its captured policy revision returns allow, confirm, or deny for that operation. Side effects require approval by default, shell networking has a separate setting, and destructive model operations are always denied.
Approval cannot be reused as a blank cheque
An approval covers one exact request. The challenge records its operation, canonical argument digest, resource scope, policy revision, decision fingerprint, and expiry. Changing the path, command, scope, or revision produces a different proof requirement. Only the resulting AuthorizedInvocation can enter a private adapter.
Cancellation or expiry withdraws the challenge and stops the owning run. Late answers cannot wake abandoned work, and approval for one command carries no authority for a nearby command with slightly different arguments.
File access is rooted in an open directory
myPAL's native file tools retain an open descriptor for the workspace root. Every requested path must be relative and composed of normal components. Absolute paths, parent traversal, empty paths, excessive nesting, and symlink traversal are rejected. On Linux, the root and its descendants are opened with no-symlink resolution and NOFOLLOW, walking outward from the retained descriptor so a path swap cannot redirect the operation between validation and use.
Writes reject symlinked targets, non-regular files, and hardlinks. New content goes to a private sibling, is synchronized, checked against the original target identity, and published with an atomic rename.
edit_file accepts bounded line-oriented hunks against an existing UTF-8 text file and validates every source coordinate before replacement. Stale context, malformed patches, unsupported input, oversized files, concurrent mutation, and proposals such as ../../.ssh/config end in typed failures.
The shell runs inside a smaller machine
Shell access receives its own execution boundary because a command interpreter can express more actions than a static classifier can enumerate. On Linux, myPAL launches commands through Bubblewrap with new namespaces and a cleared environment. The process sees a private temporary directory, a read-only system toolchain, and the selected workspace as its writable working tree. HOME points into that workspace, while credentials from the host environment stay outside the child process.
Network access begins disabled. An authorized network operation adds the host network namespace and mounts only the files needed for name resolution and TLS, all read-only.
Time and output are bounded for every command.
Cancellation or timeout sends TERM to the process group, waits through a short grace period, then sends KILL. Children therefore share the lifetime of the operation that created them.
Known dangerous command forms receive another check immediately before process creation. Recursive deletion and similar risky commands require confirmation. Filesystem formatting, raw block-device writes, shutdown attempts, and deletion of / or system directories are hard denied. The sandbox carries the main containment guarantee because pattern matching cannot establish the behavior of arbitrary shell code.
Tool output has no authority
Files, web pages, MCP responses, shell output, and retrieved memory can contain instructions aimed at the model.
myPAL returns them inside an untrusted data envelope whose closing characters are encoded. Sensitive fields are recursively redacted, and byte budgets cap how much context or durable trace space one response can consume. Oversized values retain a preview and digest. Prompt injection remains possible at the model layer, with the source's lower trust preserved in the context it receives.
The loop is bounded too
A confused run can waste resources through repeated failures, redundant reads, or a process that never returns. myPAL bounds model turns, tool deadlines, result sizes, history, and durable content. Its tool-call guardrail tracks canonical argument hashes across turns, blocking identical failed write_file and edit_file requests until their arguments change. Repeated reads and other failures receive structured guidance, with stricter thresholds available through hard-stop mode.
How the guarantees get weaker
A broad workspace increases the writable blast radius. Permitting non-destructive side effects removes the human gate from file writes and local execution, while permissive shell-network policy extends that authority to networked commands. Each MCP server contributes another executor governed by its credential scope and the remote service's authorization.
Shell access creates the largest expansion. Bubblewrap confines a command to its mounted environment, but arbitrary code can reach everything writable inside that environment. Credentials, harness configuration, and unrelated personal files therefore belong outside the selected workspace.
Each permissive choice moves the boundary outward. The strongest myPAL profile keeps the workspace narrow, exposes only required capabilities, asks before side effects, separates network approval, and leaves credentials outside every writable mount. Risky work begins with a deliberate authority change.
Programmatically unable
Software can contain implementation defects. Operating systems can have sandbox escapes, and external services can enforce their scopes incorrectly. Safe by default describes the authority myPAL grants under expected operation and the boundaries independently tested around it.
Within those boundaries, the model cannot grant itself a missing tool, reuse approval for changed arguments, escape a rooted file adapter through a symlink, or add network access to an unauthorized shell. Those decisions belong to code outside the model's control.
The one-line version
myPAL is safe by default because dangerous capability exists only after deliberate authorization.