Least privilege sounds simple:
Give the workload only the access it needs.
For autonomous agents, implementing that principle requires more work.
Agents combine multiple capabilities during one workflow: filesystem, shell, APIs, credentials, MCP tools, model providers, databases, and cloud resources.
A useful policy therefore needs to describe more than one permission. It needs to describe an operating envelope.
Start with the business workflow
Do not begin by asking:
What should we block?
Begin with:
What does this agent need to accomplish?
Example business objective:
Read a Jira ticket, modify one repository, run tests, and open a pull request.
Decompose it:
Read Jira ticket
|
Clone repo
|
Modify files
|
Run tests
|
Call model
|
Push branch
|
Open PR
Every step implies a capability.
Build a capability matrix
| Step | Resource | Action | Credential |
|---|---|---|---|
| Read ticket | Jira | Read issue | Jira OAuth |
| Clone repo | GitHub | Repo read | GitHub App |
| Edit code | Filesystem | RW project | none |
| Run tests | Process | Execute toolchain | none |
| Inference | Model | Completion/chat | provider |
| Push branch | GitHub | Write branch | GitHub App |
| Open PR | GitHub | Create PR | GitHub App |
Now define policy from evidence rather than guesswork.
Apply default deny
Start from:
Network: deny
Filesystem: deny except runtime baseline
Tools: deny
Providers: none
Cloud access: none
Then add required capabilities.
This prevents accidental privilege from becoming invisible.
OpenShell follows this philosophy in its restrictive default policy: outbound network access is denied unless another policy or provider rule permits it.
Layer 1: Filesystem policy
Define read-only paths, read/write paths, and paths that should remain unreachable.
/workspace/repo RW
/usr R
/lib R
/tmp RW
/home/user DENY
/root DENY
/run/secrets DENY
The working directory should be intentionally narrow.
Layer 2: Process policy
Ask:
- Which user should the agent run as?
- Does it need root?
- Which Linux capabilities are required?
- Does it need package installation?
- Can it launch nested containers?
- Can it access the Docker socket?
For most agent workloads:
root: no
privilege escalation: no
Docker socket: no
host namespace: no
Exceptions should be explicit.
Layer 3: Network policy
Inventory every legitimate destination.
api.github.com
jira.company.com
model.company.internal
packages.company.internal
Everything else should remain denied.
For sensitive systems, move toward request-level policy where the technology supports it.
Example:
GitHub:
read repo allowed
create PR allowed
delete repo denied
Layer 4: Credentials
For every credential ask:
- What resource does it access?
- What operations does it permit?
- How long is it valid?
- Can the agent read the raw value?
- Can it be used against another destination?
Prefer credentials that are scoped, short-lived, workload-specific, destination-bound, and centrally revocable.
Layer 5: MCP tools
Create explicit tool permissions.
GitHub MCP
+-- read_file ALLOW
+-- create_branch ALLOW
+-- open_pull_request ALLOW
+-- merge_pull_request DENY
`-- delete_repository DENY
Do not treat "MCP server allowed" as sufficiently granular for high-risk servers.
Layer 6: Model providers
Define which model endpoints the agent may use.
engineering-agent:
inference.company.internal -> allow
public model endpoints -> deny
Model routing should match data classification.
Layer 7: Downstream IAM
The runtime should not be the only policy layer.
Use downstream IAM too.
OpenShell:
allows GitHub endpoint
GitHub App:
scoped to repo A
Repository rules:
protected main branch
Now multiple controls have to fail before the agent can exceed its intended role.
Define policies by agent role
At scale, create reusable role templates.
Software Engineering Agent
Source repo RW, issue tracker read, CI read, approved model access, production denied.
Data Engineering Agent
Dev data RW, staging warehouse RW, production read-only, dbt repo RW, limited scheduler access.
SRE Agent
Logs read, metrics read, Kubernetes namespace limited write, IAM denied, raw secrets denied.
Support Agent
CRM read, ticketing RW, refund tool approval required, admin APIs denied.
Role templates make policy reusable without pretending every workload is identical.
Manage policy as code
Agent policies should live in Git.
Use pull requests, code owners, tests, approvals, version history, and automated deployment.
A request to add a wildcard endpoint should be reviewed like a firewall or IAM change.
OpenShell's YAML policy model fits naturally into this workflow.
Test policy before production
For every allowed capability, test whether the agent can complete the business workflow.
For every denied capability, test whether the agent can exceed it.
Negative tests should include unapproved domains, restricted files, unauthorized APIs, prohibited MCP tools, credential exfiltration, and privilege escalation.
Least privilege is not proven until the denial paths work.
Detect policy creep
Over time teams will ask:
Can we just add this one endpoint?
Can we mount this directory?
Can we reuse this token?
The agent slowly accumulates privilege.
Track the number of network destinations, writable paths, credentials, tools, production permissions, and administrative actions.
Unexpected growth should trigger review.
The goal is useful constraint
Least privilege should not make the agent unusable.
The target is:
Maximum useful autonomy
within
minimum necessary privilege
That balance is the core design problem.
How Anpu Labs builds agent policies
Our Secure Agent Infrastructure Assessment maps the workflow first.
Then we convert each workflow into required files, processes, network destinations, API actions, credentials, MCP tools, and model endpoints.
That becomes the policy baseline for the pilot.
References
- NVIDIA OpenShell — Default Policy: https://docs.nvidia.com/openshell/latest/how-it-works/policies/default-policy
- NVIDIA OpenShell — Policy Schema: https://docs.nvidia.com/openshell/latest/reference/policy-schema
- NVIDIA OpenShell — Providers: https://docs.nvidia.com/openshell/how-it-works/providers/overview




