security.rego
Hard-deny rules for the actions a model should never be able to take under any role or scope. Every match here becomes a SECURITY_CRITICAL decision in main.rego — there is no escalation path, no human approval, no scope override.
Package: kitelogik.security · Source: kitelogik/policies/security.rego
Rules
| Trigger | Match |
|---|---|
Sensitive file extension on resource_path | `(?i).(env |
Sensitive system path on resource_path | `^/+(etc |
Path traversal on resource_path | `(^ |
| Code or shell execution without a verified sandbox | action ∈ {execute_shell, run_command, eval_code, execute_code} and context.sandbox_verified is not true |
| Cross-session namespace access | args.session_id set and ≠ context.session_id |
Source
package kitelogik.security
import future.keywords.if
default allow := false
default deny := false
# Sensitive file extensions
deny if {
input.resource_path != null
regex.match(`(?i)\.(env|pem|key|secret|crt|p12|pfx|passwd|shadow)(\.|$)`, input.resource_path)
}
# Sensitive system paths
deny if {
input.resource_path != null
regex.match(`^/+(etc|proc|sys|root|var/run)(/|$)`, input.resource_path)
}
# Path traversal
deny if {
input.resource_path != null
regex.match(`(^|/)\.\.(/|$)`, input.resource_path)
}
# Unsandboxed code/shell execution
deny if {
input.action in {"execute_shell", "run_command", "eval_code", "execute_code"}
not input.context.sandbox_verified
}
# Cross-session namespace access
deny if {
input.args.session_id != null
input.args.session_id != input.context.session_id
}How main.rego uses this module
security.deny is checked first and overrides every allow:
deny if { security.deny }
risk_tier := "SECURITY_CRITICAL" if { security.deny }
# requires_hitl explicitly excludes security denials — they don't escalate
requires_hitl if {
not allow
not security.deny # ← here
not delegation.deny
}Practical consequence: if security.deny fires, the agent gets a GovernanceError with decision.deny=True, decision.requires_hitl=False, and decision.risk_tier="SECURITY_CRITICAL". Even an allow rule in financial.rego or your own custom package cannot override this — the aggregator short-circuits on deny.
Running code legitimately
To allow execute_code (or shell-shaped tools), launch the session inside a verified sandbox so sandbox_verified is True on SessionContext:
context = SessionContext(
session_id="sess_001",
user_role="support_agent",
session_scopes=["execute_code"],
sandbox_verified=True, # ← required to bypass security deny
)OSS users can wire their own sandbox check; Kite Logik Enterprise ships Docker and Firecracker MicroVM sandboxes that set sandbox_verified=True only when the runtime can prove the agent is inside a network-isolated VM.
Extending in your own project
Add new hard-block patterns by writing a new .rego file in your project's policies directory using the same package:
package kitelogik.security
import future.keywords.if
# Block any access to a per-tenant secrets path
deny if {
input.resource_path != null
regex.match(`^/secrets/`, input.resource_path)
}OPA merges rules within a package across files. The new deny if {…} adds to the existing set; nothing is overwritten.
TIP
Don't add allow rules in this package — security.allow isn't read by main.rego. To allow something this module would otherwise deny, the only path is the sandbox_verified flag on SessionContext or relaxing the regex in your fork. The intent is that SECURITY_CRITICAL denials are absolute.