Skip to content

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

TriggerMatch
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 sandboxaction ∈ {execute_shell, run_command, eval_code, execute_code} and context.sandbox_verified is not true
Cross-session namespace accessargs.session_id set and ≠ context.session_id

Source

rego
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:

rego
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:

python
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:

rego
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.

Released under the Apache 2.0 License.