# OpenHuman Command Permission Tiers: How classify_command Gates Security Decisions

> Discover OpenHuman's command permission tiers and how AutonomyLevel gates security decisions. Understand Read, Write, Network, Install, and Destructive commands.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: security
- Published: 2026-09-01

---

**OpenHuman enforces a tiered security model where the `AutonomyLevel` setting (Read-only, Supervised, or Full) determines whether shell commands classified as Read, Write, Network, Install, or Destructive are Allowed, Prompted, or Blocked.**

The `tinyhumansai/openhuman` repository implements a fine-grained security policy that governs how AI agents execute shell commands. At its core, the system uses the `classify_command` method to categorize command risk levels and the `gate_decision` method to enforce session-specific **OpenHuman command permission tiers**.

## Understanding the Three Permission Tiers (AutonomyLevel)

OpenHuman defines three distinct autonomy tiers in `src/openhuman/security/policy/types.rs#L45` that control how permissive a session is. These tiers act as the primary gate for all command execution.

### Read-only Tier

In **Read-only** mode, the policy allows only commands classified as `Read`. Any command that modifies the filesystem, accesses the network, or performs destructive operations receives a `Block` decision. This tier is ideal for safe exploration and data inspection where no system changes are permitted.

### Supervised Tier

**Supervised** mode enables write-capable operations but requires user approval. Commands classified as `Write`, `Network`, or `Install` trigger a `Prompt` decision, presenting an approval card to the user before execution. Destructive commands may also be blocked or prompted depending on policy configuration.

### Full Tier

**Full** autonomy removes all restrictions, mapping every `CommandClass` to `Allow`. This tier should only be used in trusted environments where the AI requires unrestricted system access.

## The Command Classification System (CommandClass)

Before gating occurs, every command is classified according to its potential impact. The `CommandClass` enum, defined in `src/openhuman/security/policy/types.rs#L82`, contains five distinct variants:

- **Read** – Commands that only observe data (e.g., `cat`, `ls`, `grep`)
- **Write** – Commands that modify the filesystem (e.g., `touch`, `mv`, `echo > file`)
- **Network** – Commands performing network I/O (e.g., `curl`, `wget`, `ping`)
- **Install** – Package manager actions (e.g., `npm install`, `pip install`)
- **Destructive** – Commands that delete or irrevocably alter data (e.g., `rm -rf`, `dd`, `mkfs`)

The classification logic handles complex command strings by splitting them into segments (respecting pipelines, `&&`, and `||` operators) and computing the **maximum** risk class across all segments. If any segment is `Destructive`, the entire command inherits that classification.

## How classify_command and gate_decision Work Together

The security flow involves two critical methods implemented in [`src/openhuman/security/policy/policy_command.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/policy_command.rs) and [`src/openhuman/security/policy/policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/policy.rs).

### The Classification Process

When a tool invokes `SecurityPolicy::classify_command(&self, cmd: &str) -> CommandClass`, the method parses the command string and checks each segment against whitelists of safe verbs. It returns the highest `CommandClass` found among all segments, ensuring that a seemingly safe command appended with a destructive operation is correctly flagged.

### The Gate Decision Mapping

After classification, `SecurityPolicy::gate_decision(class: CommandClass) -> GateDecision` maps the class to an action based on the current `AutonomyLevel`:

| CommandClass | Read-only Tier | Supervised Tier | Full Tier |
|--------------|----------------|-----------------|-----------|
| **Read** | Allow | Allow | Allow |
| **Write** | Block | Prompt | Allow |
| **Network** | Block | Prompt | Allow |
| **Install** | Block | Prompt | Allow |
| **Destructive** | Block | Block/Prompt | Allow |

The `GateDecision` enum (defined in [`src/openhuman/security/policy/types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/types.rs)) has three variants: `Allow`, `Prompt`, and `Block`.

### Enforcement in Tools

Tools that invoke shell commands check the policy before execution. In [`src/openhuman/tools/impl/system/shell.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/system/shell.rs), the implementation consults the security policy:

```rust
match self.security.gate_decision(self.security.classify_command(&shell_cmd)) {
    GateDecision::Allow => { /* Execute command */ },
    GateDecision::Prompt => { /* Request user approval */ },
    GateDecision::Block => { /* Abort with security error */ },
}

```

This ensures a fail-closed model where unknown commands default to the most restrictive action appropriate for the current tier.

## Practical Implementation Examples

### Manual Policy Usage

You can instantiate and query the policy directly in Rust applications:

```rust
use openhuman::security::{SecurityPolicy, AutonomyLevel, CommandClass, GateDecision};

fn main() {
    // Initialize policy for supervised session
    let policy = SecurityPolicy::new(AutonomyLevel::Supervised);
    
    let cmd = r#"git clone https://example.com/repo.git && rm -rf repo"#;
    
    // Classify the compound command
    let class = policy.classify_command(cmd);
    
    // Query the gate decision
    let decision = policy.gate_decision(class);
    
    println!("Class: {:?}, Decision: {:?}", class, decision);
    // Output: Class: Destructive, Decision: Prompt
}

```

### Tool Integration Pattern

Tools that wrap shell execution implement the security check as follows:

```rust
fn execute_shell_command(&self, args: &[String]) -> Result<(), String> {
    let shell_cmd = args.join(" ");
    
    // Security gate check
    match self.security.gate_decision(
        self.security.classify_command(&shell_cmd)
    ) {
        GateDecision::Allow => {
            std::process::Command::new("sh")
                .arg("-c")
                .arg(&shell_cmd)
                .status()
                .map_err(|e| e.to_string())?;
            Ok(())
        },
        GateDecision::Prompt => Err("User approval required".into()),
        GateDecision::Block => Err("Command blocked by security policy".into()),
    }
}

```

## Key Source Files

The security policy implementation spans several critical files in the `tinyhumansai/openhuman` repository:

- [`src/openhuman/security/policy/types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/types.rs) – Defines `AutonomyLevel`, `CommandClass`, and `GateDecision` enums
- [`src/openhuman/security/policy/policy_command.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/policy_command.rs) – Implements `classify_command` and parsing logic for shell segments
- [`src/openhuman/security/policy/policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/policy.rs) – Ties classification and gate decisions together in the public `SecurityPolicy` API
- [`src/openhuman/tools/impl/system/shell.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/system/shell.rs) – Example tool integration showing policy enforcement
- [`src/openhuman/security/policy/policy_tests_part_01_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/policy_tests_part_01_tests.rs) – Unit tests mapping command classes to decisions for each autonomy tier

## Summary

- **OpenHuman uses three permission tiers** (Read-only, Supervised, Full) defined in [`src/openhuman/security/policy/types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/types.rs) to control command execution scope.
- **Commands are classified** into five risk categories (Read, Write, Network, Install, Destructive) by the `classify_command` method in [`src/openhuman/security/policy/policy_command.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/policy_command.rs).
- **Gate decisions** map classifications to Allow, Prompt, or Block actions based on the current `AutonomyLevel`.
- **Multi-segment commands** are evaluated by their highest-risk component, ensuring pipelines containing destructive operations are properly flagged.
- **Tools enforce the policy** by checking `gate_decision` before executing shell commands, creating a centralized, auditable security boundary.

## Frequently Asked Questions

### What are the three AutonomyLevel tiers in OpenHuman?

The three tiers are **Read-only**, **Supervised**, and **Full**. Read-only permits only `Read` class commands and blocks everything else. Supervised allows `Read` commands silently but prompts for approval on `Write`, `Network`, `Install`, and `Destructive` operations. Full permits all command classes without user intervention.

### How does classify_command determine the CommandClass?

The `classify_command` method parses the command string into segments, handling operators like pipes and `&&` chains. It checks each segment against internal whitelists to assign a class, then returns the **maximum** risk level found using the `CommandClass::max` implementation. This ensures compound commands are classified by their most dangerous component.

### What happens when a command is classified as Destructive?

In **Read-only** tier, Destructive commands are always **Blocked**. In **Supervised** tier, they typically trigger a **Prompt** for user approval or may be blocked depending on policy configuration. In **Full** tier, they are **Allowed** to execute immediately. The exact mapping is determined by `gate_decision` in [`src/openhuman/security/policy/policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/policy.rs).

### Where is the security policy enforced in the codebase?

Policy enforcement occurs in tool implementations, specifically in [`src/openhuman/tools/impl/system/shell.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/system/shell.rs), where the tool calls `self.security.gate_decision()` with the classified command class before executing any shell command. This centralizes security checks across all tooling that may invoke system commands.