Skip to content

Policy Engine

Define allow/deny rules for commands and file paths to enforce operational guardrails.

The policy engine defines guardrails that control which commands can be executed and which file paths can be accessed. Rules apply equally to human operators and AI agents connected via the MCP server.

Policy Modes

ModeBehavior
offPolicy evaluation is disabled. All operations are allowed.
warnViolations are logged to the audit log but not blocked. Useful for testing new rules.
enforceViolations are blocked and the operation is rejected with an error.

Configuration

Policies are defined in nefia.yaml under the policy key:

yaml
policy:
  mode: enforce
 
  deny_commands:
    - "^rm\\s+-rf\\s+/"
    - "^(shutdown|reboot|halt|poweroff)"
    - "^mkfs\\."
    - "^dd\\s+if=.+of=/dev/"
 
  allow_commands:
    - "systemctl\\s+(status|restart|reload)"
    - "journalctl"
    - "docker\\s+(ps|logs|inspect)"
 
  deny_paths:
    - "/etc/shadow"
    - "/etc/sudoers"
    - "\\.ssh/.*private"
 
  allowed_roots:
    - /var/www
    - /home/deploy
    - /etc/nginx

All command and path rules use Go regular expressions matched against the full command string or file path. Patterns without ^ (start) or $ (end) anchors match anywhere in the string — for example, rm also matches format and chromium. Use ^rm to match only commands starting with rm.

Input Length Limit (ReDoS Defense)

To prevent Regular Expression Denial of Service (ReDoS) attacks via pathologically crafted input, the policy engine enforces a maximum input length of 8,192 bytes (2× Linux PATH_MAX) on all evaluated strings — commands, paths, and roots.

Inputs exceeding this limit are denied unconditionally, even in warn mode. This is intentional: relaxing the limit in warn mode would defeat the protection entirely by allowing regex evaluation on arbitrarily large inputs.

Evaluation Order

1

Deny rules are checked first. If the command matches any pattern in deny_commands (or the path matches deny_paths), the operation is blocked.

2

Allow rules are checked second. If allow_commands is non-empty and the command does not match any allow pattern, the operation is blocked.

3

Allowed roots are checked for file operations. The resolved file path must fall within one of the directories listed in allowed_roots.

4

If no rules match, the operation is allowed. An empty policy permits everything.

RBAC Roles

For more granular control, define named roles with host-specific command and path rules:

yaml
policy:
  mode: enforce
  roles:
    - name: read-only
      hosts: [".*"]
      allow_commands: ["cat|head|tail|less|grep|find|ls|stat", "systemctl\\s+status"]
      deny_commands: ["^.*"]  # deny everything not explicitly allowed
    - name: deploy
      hosts: ["^web-", "^worker-"]
      allow_commands: ["systemctl\\s+(restart|reload)", "docker\\s+(pull|up|down|restart)"]
      deny_commands: ["^rm\\s+-rf", "^(shutdown|reboot)"]
      allowed_roots: [/var/www, /home/deploy]

Roles are selected from the target host's role field. roles[].hosts is evaluated as a host ID regex, not a group selector and not an operator-identity rule.

MCP Server Integration

When the MCP server is running (nefia mcp serve), the policy engine evaluates every tool call from AI agents using the same rules. There is no privilege escalation path for MCP clients.

plaintext
[MCP] Tool call: exec command="rm -rf /tmp/*" target="web-01"
[MCP] Policy violation: command matches deny rule "^rm\s+-rf\s+/"
[MCP] Result: DENIED (policy: enforce)

Testing Policies

Use nefia plan exec to dry-run an operation against the policy engine without executing it:

bash
nefia plan exec --target my-server -- rm -rf /tmp/cache
nefia plan exec

Command: rm -rf /tmp/cache Target: my-server (10.99.0.2) Policy: DENIED — matches deny_commands pattern: "^rm\s+-rf\s+/"

No commands were executed.

MCP Tools for Policy Testing

AI agents can test policies programmatically:

ToolDescription
nefia.policy.testTest whether a specific command or path would be allowed or denied by the policy engine.
nefia.policy.test_batchTest up to 50 command/path combinations in a single call for efficient pre-flight checks.
nefia.policy.capabilitiesList all allowed operations for a given host, showing what commands and paths the current policy permits.

Practical Examples

Read-only monitoring access
yaml
policy:
  mode: enforce
  roles:
    - name: monitoring
      hosts: [".*"]
      allow_commands: ["uptime|free|df|top -bn1", "systemctl\\s+status", "cat\\s+/var/log/"]
      deny_commands: ["^.*"]
Restrict file access to application directories
yaml
policy:
  mode: enforce
  deny_paths: ["/etc/(shadow|passwd|sudoers)", "\\.ssh/", "\\.env"]
  allowed_roots: [/var/www/myapp, /var/log/myapp]
Block destructive commands globally
yaml
policy:
  mode: enforce
  deny_commands:
    - "^rm\\s+-rf\\s+/"
    - "^(shutdown|reboot|halt|poweroff)"
    - "^mkfs\\."
    - "^dd\\s+if=.+of=/dev/"
    - "^chmod\\s+777"
    - "^curl.*\\|\\s*(bash|sh)"
Security Overview

Understand Nefia's defense-in-depth security architecture.

Audit Logging

Track policy violations and all operations with tamper-evident logs.