Security
This page is for security reviewers. It describes how the platform limits what an AI agent can do, what is recorded, which data leaves your network, and where the limits of these controls are.
Identities and permissions
Section titled “Identities and permissions”| Identity | What it is | Used for |
|---|---|---|
| Bot user (one per agent) | A Polarion user named bot-<name>, with a personal access token held by the runner |
Everything the agent writes in Polarion: items, comments, links, status changes |
| Runner admin account | A Polarion token held by the runner | Reading the Agent Pool and engagements, the watcher, reading field configuration, writing agentRun items and the “needs you” comment |
| People | Your Polarion users | Hiring, assigning, answering, approving; the views call the runner with their own session |
- Hiring is a Polarion permission. The hire wizard calls the app’s server script with the person’s own
session, so Polarion checks their right to manage the project. The bot user gets the project roles
project_userandproject_assignable; letting it go removes its project roles. - A bot that is not a project member cannot see the project. Its permissions are whatever your project configuration gives those roles.
- Pausing an engagement stops the watcher from waking the agent. Retiring an agent in the pool stops all its work.
- The runner validates every call from the views against Polarion: the caller’s session token (with the session cookie) must be able to read the project concerned.
Credentials
Section titled “Credentials”| Credential | Where it lives | Reaches the model or a sandbox? |
|---|---|---|
| Runner admin Polarion token | Bootstrap secret file /run/secrets/admin_token |
No |
| Agent (bot user) Polarion tokens | Runner secret store, encrypted; set in Administration → Credentials | No |
| Model provider key | Runner secret store, encrypted; set in Administration → Credentials; added to sandbox requests by the OpenSandbox credential vault | No |
| MCP connection credentials | Runner secret store, encrypted; set when the connection is registered | No |
| Store encryption key | Bootstrap secret file /run/secrets/secret_key |
No |
| Run token | Runner memory; given to the agent’s harness for one run | Valid for one run only |
- The secret store is write-only from the browser: you can set a secret and see whether it is set, when and by whom, never its value.
- The gateway and the git proxy add connection credentials on the way out. The agent only ever sees tool results.
- The runner silences the request logs of its HTTP clients, because some servers carry keys in the URL.
Who may administer
Section titled “Who may administer”The platform adds no users, roles or permissions of its own: Polarion’s roles decide. The Agent Runner asks
Polarion who the caller is (through the app’s whoami endpoint, with the caller’s own session) and lets a person
change credentials, register and re-review MCP servers, run the field test and stop or remove sandboxes only when
they are an administrator of the Agent Pool project — Polarion role project_admin there, or a global
admin. Everyone with read access to the Agent Pool can look at the Agency and Administration pages; the pages
say “Read only” for them and the runner refuses the writes (HTTP 403) even when called by hand.
Everything else is governed by Polarion as usual: hiring needs the right to manage the work project’s members, setup writes the data model and pages as the person who clicks Apply, approvals and answers are comments and status changes made as that person.
flowchart LR classDef pol fill:#e0f2f1,stroke:#00897b,color:#004d40 classDef run fill:#ede7f6,stroke:#7e57c2,color:#311b92 classDef you fill:#fff8e1,stroke:#ffb300,color:#7a4f01 classDef bad fill:#ffebee,stroke:#e53935,color:#b71c1c P["<b>Person</b><br/><small>browser session</small>"]:::you --> R["<b>Agent Runner</b><br/><small>operator endpoint</small>"]:::run R --> W["<b>Polarion</b><br/><small>whoami: roles in the Agent Pool</small>"]:::pol W -->|project_admin or admin| OK["<b>Allowed</b><br/><small>change made, recorded with the name</small>"]:::run W -->|other roles| NO["<b>Refused</b><br/><small>HTTP 403, page read only</small>"]:::bad
Where secrets live
Section titled “Where secrets live”The runner reads no secret from environment variables or a .env file. There are two classes:
- Bootstrap secrets are what the runner needs to start, before any page exists: the store encryption key
(
secret_key), the runner’s own Polarion administrator token (admin_token), the PocketBase superuser password and the OpenSandbox API key. Each is one file at/run/secrets/<name>, provided by Docker secrets, a Kubernetes Secret volume, a CSI secrets-store driver or External Secrets. Rotation = replace the file and restart. - Operational secrets are what agents work with: the model key, one Polarion token per agent and the
credentials of connected systems. Agent Pool administrators set them in Administration → Credentials; they are
stored encrypted (AES via Fernet with
secret_key) in the runner’s store and read by the runner when needed, without a restart.
Properties of the store:
- The browser never receives a secret value back. The page shows whether an item is set, when and by whom; a paste field is write-only. A stored value can be tested (the model key answers a one-token request, an agent token signs in as the agent) but not displayed.
- Writes are attributed. Every value is written as the administrator who pastes it and recorded with their name and time.
- The encryption key is itself a bootstrap secret file. Without it the store is unreadable, so keep it in your secret management, separate from backups of the store.
See Credentials.
Network controls for sandboxes
Section titled “Network controls for sandboxes”Agents with a sandbox harness (Claude Code, Codex) work in one sandbox per task.
- Deny by default. Egress is allowed only to the runner’s sandbox entrance, the model endpoint, hosts you configure for all sandboxes, and the websites listed on the engagement (with their subdomains). The list is re-applied on every run.
- The internet is read-only. The sandbox’s egress proxy answers 403 to every method except GET, HEAD and OPTIONS, except for the model endpoint and private addresses (the sandbox entrance). This relies on TLS interception by the sandbox’s credential proxy.
- The sandbox entrance serves only the gateway and the git proxy, not the runner’s API.
- No credentials inside. The model key is added by the credential vault; git and MCP credentials are added by the gateway.
- Web tools. Web search is always off. Claude Code’s WebFetch is on only when the engagement lists websites. Pages read with WebFetch, curl or wget are recorded in the run ledger.
- Limits. The agent runs as an unprivileged user. Each sandbox has CPU and memory limits, a maximum lifetime, and the number of running sandboxes is capped. Admins can pause, resume or delete sandboxes in Administration → Sandboxes.
See Sandboxes.
Human-in-the-loop controls
Section titled “Human-in-the-loop controls”| Control | Effect |
|---|---|
| Pool lifecycles | Only available agents work, only approved skills reach a prompt, only active connections are served |
| Grants and scopes | A connection must be used by the agent, active and granted on the engagement; scoped systems are locked until a scope is set |
| Tool policies | read runs, approve is held for the supervisor, block is refused |
| Tool drift | Changed or removed tools are held until a person reviews the policy again; new tools are never offered unreviewed |
| Changes to human-written items | Title, description, fields and images of items not marked aiGenerated are held for approval |
| Workflow | Agents may not move items into approved, accepted, released, verified, done, closed, rejected or obsolete, nor run signature-bound actions; request_review is for people only |
| Task approval | The supervisor approves or sends back every top-level task |
| Git | Push only to agent branches; merge is an MCP call under policy |
| Memories | Proposed by agents, approved (and editable) by a person before they reach a prompt |
| Budgets | Hard caps per engagement (see Budgets) |
See Governance for how to set these up.
Auditability
Section titled “Auditability”| Question | Where to look |
|---|---|
| What did this agent do on this task? | The Agent Run items (ai_run_of the task): action log, ledger, gateway calls, transcript |
| Who or what created this item? | aiGenerated, authorAgent, ai_produced_by → task, ai_created_by_run → run; the Provenance panel |
| Who approved a held change? | The decision comment on the task (written as that person) and PocketBase approvals |
| What did agents do in connected systems? | Ledger entries with URL and title; Administration → Gateway |
| Which instructions did the agent have? | Agent brain (exact text); skillRevisions and memories on the run |
| What did a sandbox run do? | sandbox field on the run: commands, web pages, sites, budget cap |
| Everything AI in a project | AI Reports → AI audit (CSV export) |
What goes to the model provider
Section titled “What goes to the model provider”The model provider receives everything in the agent’s context:
- the instructions: persona, skills, project instructions, memories, supervisor and team names, connected systems and their project notes;
- the task: title, description, links, sub-tasks and the comment thread;
- every tool result: work item text and fields, documents, comments, results from connected systems, and in a sandbox the files, command output and web pages the agent reads.
Choose the model endpoint according to your data classification. A company LLM gateway can be used instead of a public provider. Anthropic requests use prompt caching.
Data that stays on your infrastructure: Polarion, PocketBase, sandboxes and the runner. Data that reaches a connected MCP server is what the agent sends as tool arguments.
What it does not protect against
Section titled “What it does not protect against”- Prompt injection. Text in work items, documents, tool results and web pages reaches the model. The
controls limit what an agent can do, not what it believes. A read tool with policy
readruns without a person. - Data in GET requests. The read-only internet blocks uploads, but an agent can still put data into the URL of a GET request to an allowed site. Allow only sites you trust.
- AI-made items are open to all agents. Agents change items marked
aiGenerateddirectly, including items another agent made. - Not every Polarion write is held. Comments, links, moving items into documents, editing document text paragraphs and document comments are not held for approval; they are limited by the bot user’s Polarion permissions.
- Who may decide. The runner checks that the decider can access the project and records the decision under their name. It does not restrict decisions to the engagement’s supervisor; use Polarion permissions on tasks for that.
- Agency and Administration admin functions (secrets, connection discovery, sandboxes) check read access to the Agent Pool project. Restrict that project to administrators.
- Codex runs have no in-run cost cap. The budget is checked before each run.
- Costs are estimates, computed from token usage and a price table in the runner.
- Scope matching checks that a scope argument contains a scoped value. Choose scope values that are specific (full paths rather than short names).
- PocketBase holds content: held calls with their arguments and results, and full chat histories. There is no automatic retention.
- Transcripts are attachments on agentRun items, readable by everyone who can read the project.