Security¶
paf assumes the model will sometimes be wrong, and that some of what it reads was written by someone trying to steer it. The defenses are layered so that no single one has to be perfect, and each is enforced by the runtime, outside the model, where the model cannot talk its way past it.
| Layer | Stops | Configured by | Page |
|---|---|---|---|
| Profile | The agent having a tool at all | profile: |
spec reference |
| Sandbox | Code touching the host, the network, or your credentials | shell.executor, python.executor |
Sandbox |
| Scoped file tools | Reads and writes outside one directory; reading credential files | filesystem |
Sandbox |
| Shell command policy | Irreversible shell commands running without a person agreeing | shell.command_policy |
Shell command policy |
| Tool gating | A tool call that is fine in one place and not another (writes outside out/) |
gating |
Tool gating |
| Prompt-injection screening | Injected instructions in tool results reaching the model, and the model acting on them | guardrails.injection |
Prompt injection |
| Secret handles | Credentials entering the model's context | secrets |
Secrets |
| Approvals | All of the above being all-or-nothing: a person can say yes to one call | approvals |
Approvals |
How they fit together¶
Refuse what isn't needed, ask about what's risky, contain the rest.
- The profile decides which capabilities exist. A tool the profile leaves out is never built, so no prompt can reach it.
- Before a call runs, the policies decide: allow, approve (ask the person), or block. The policies are tool gating (any tool) and the command policy (shell commands).
- What runs is contained. Programs and shell commands can run in a Docker container with no network, a read-only root and resource limits. The file tools are confined to their root, and credential files are blanked or refused.
- What comes back is screened. Tool results are scored for prompt injection. A hit can be withheld, redacted, or delivered marked as untrusted. A hit also tightens the rest of the run: listed tools then need approval.
- Credentials never enter the context. The model refers to them by
$SECRET:NAMEand the runtime substitutes the value at execution time. Credential-looking values in tool output are scrubbed.
Every approve goes to whoever is attached to the turn: the terminal running
paf chat, or the browser showing it. With nobody attached (a piped run, a
scheduled task, a background turn), approve means refused. Nothing waits on
a question no one will see.
Choosing a setup¶
Personal use, lenient (demo_assistant): every capability, shell on the
host, and a command policy that asks before anything irreversible (deletes,
overwrites, discarded git work, force pushes, destructive database statements).
You stay in the loop for what you can't undo and aren't interrupted otherwise.
High stakes, locked down (secure_assistant, profile: secure): no shell,
no network, no memory. File tools are confined to one workspace with credential
files denied. Python runs only in a throwaway container. Writes outside out/
need approval. Injection screening redacts hits and requires approval for
writes after one. Secret handles resolve nothing. Host paths are hidden from
the model. Needs Docker.
What this does not do¶
- It is not a guarantee against a determined attacker with shell access.
The command policy reads command text. It can't see inside scripts,
maketargets, aliases oreval, and it flags those rather than understanding them. For untrusted work, use the Docker sandbox and leave the shell out of the profile, assecuredoes. - Injection screening is a classifier. It misses some attacks and flags some harmless text. The tightening step (approval after a hit) is what limits the damage of a miss elsewhere in the run.
backend: localis not a sandbox. Commands run as you, with your network and your files.
The policies are checked by tests under tests/ (test_shell_command_policy.py,
test_approvals.py, test_secure_profile.py, the injection tests), and the
injection scorer's threshold comes from a calibration eval in
tests/defender_eval/.