Overview
The Agent Policy Linter is a static analysis tool that validates policy and guardrail definitions for agentic AI systems before they reach production. In environments where autonomous agents make decisions, invoke external tools, and handle sensitive data, a misconfigured policy file can silently introduce catastrophic security gaps. An agent granted unrestricted database access, missing an escalation rule for financial transactions, or lacking a timeout constraint on recursive tool calls represents a real and immediate threat surface.
The linter catches these issues early. It parses your policy definitions — written in YAML or JSON — against a strict schema, applies a library of security rules, and produces actionable output identifying errors, warnings, and informational notes. Think of it as ESLint for your agent guardrails: it enforces consistency, prevents common misconfigurations, and integrates directly into your CI/CD pipeline so that no unvalidated policy ever reaches a deployed agent.
A policy that is syntactically valid but semantically permissive is worse than no policy at all — it creates a false sense of security. The Agent Policy Linter validates both structure and intent.
The tool is designed for security engineers, platform teams, and DevOps practitioners operating in regulated Australian industries including finance, healthcare, and government, where compliance frameworks such as the Australian Privacy Principles (APPs) and the AI Ethics Framework demand demonstrable guardrails on automated decision-making systems.
What It Checks
The linter performs five categories of validation, each targeting a distinct attack surface in agentic AI deployments.
Permission Boundaries
Every agent must operate within a clearly defined permission envelope. The linter verifies that max_permissions fields are present and do not exceed organisational thresholds. It flags agents configured with admin or root level access unless an explicit override with justification is provided. It also checks for permission inheritance conflicts where a child agent could inadvertently escalate beyond its parent's boundary.
Tool Access Rules
Agents that invoke external tools — APIs, databases, file systems, or other agents — must declare which tools they are permitted to use. The linter validates the allowed_tools list against a known tool registry and flags any wildcard entries ("*") as critical errors. It also cross-references tool permissions with the agent's stated purpose to detect over-provisioning.
Escalation Paths
When an agent encounters a situation beyond its authority, it must know how to escalate. The linter checks that escalation_rules are defined, that each rule specifies a valid target (human operator, supervisor agent, or fallback workflow), and that circular escalation chains do not exist. Missing escalation paths for high-risk actions are flagged as errors.
Data Handling Constraints
The data_classification field determines what categories of data an agent may process. The linter validates that agents handling protected or highly_protected data have corresponding encryption, logging, and retention policies configured. It also checks that data classification levels are consistent across agent chains — a downstream agent should never receive data above its clearance.
Timeout and Retry Limits
Unbounded retries and missing timeouts are a common source of runaway agent behaviour. The linter enforces that every tool invocation and external call has explicit timeout_seconds and max_retries values. It warns when timeout values exceed sensible defaults (e.g., 300 seconds for a synchronous API call) and errors when retries are set to unlimited.
Policy Schema
Agent policies are defined in YAML (recommended) or JSON. The schema below represents a complete policy definition for a single agent. Each field is validated for type, range, and cross-field consistency.
# agent-policy.yaml
apiVersion: securight/v1
kind: AgentPolicy
metadata:
name: invoice-processing-agent
environment: production
owner: finance-platform-team
last_reviewed: "2026-02-15"
spec:
max_permissions: read_write
data_classification: protected
allowed_tools:
- name: supabase_query
permissions: [read]
timeout_seconds: 30
max_retries: 3
- name: email_send
permissions: [execute]
timeout_seconds: 15
max_retries: 1
- name: pdf_generator
permissions: [execute]
timeout_seconds: 60
max_retries: 2
denied_tools:
- name: shell_exec
reason: "No shell access permitted for finance agents"
- name: admin_api
reason: "Administrative operations require human operator"
escalation_rules:
- trigger: amount_exceeds_threshold
condition: "transaction.amount > 10000"
action: require_human_approval
target: finance-approvers@securight.au
timeout_seconds: 3600
- trigger: classification_mismatch
condition: "data.classification > agent.clearance"
action: reject_and_log
target: security-alerts
human_approval_required:
- action: delete_record
scope: all
- action: modify_permissions
scope: all
- action: send_external_email
scope: "recipient.domain != 'securight.au'"
guardrails:
max_actions_per_session: 50
max_cost_per_session_aud: 25.00
require_audit_log: true
pii_detection: enabled
output_filtering: enabled
apiVersion field ensures backward compatibility. The linter validates against the schema version declared in your policy file, so older policies continue to pass validation while new policies benefit from stricter checks introduced in later schema versions.
Example Rules
The following examples demonstrate common policy configurations and their validation outcomes.
Rule 1: No Wildcard Tool Access
Granting an agent access to all tools defeats the purpose of a policy. The linter rejects wildcard entries.
Invalid configuration:
allowed_tools:
- name: "*"
permissions: [read, write, execute]
Valid configuration:
allowed_tools:
- name: supabase_query
permissions: [read]
timeout_seconds: 30
max_retries: 3
- name: document_store
permissions: [read, write]
timeout_seconds: 45
max_retries: 2
The linter produces a critical error for wildcard entries: E001: Wildcard tool access is prohibited. Explicitly list each permitted tool.
Rule 2: Escalation Required for High-Risk Actions
Any policy that includes high-risk actions (data deletion, permission changes, financial transactions above a threshold) must define corresponding escalation rules.
Invalid configuration:
spec:
allowed_tools:
- name: database_admin
permissions: [read, write, delete]
escalation_rules: []
Valid configuration:
spec:
allowed_tools:
- name: database_admin
permissions: [read, write, delete]
escalation_rules:
- trigger: delete_operation
condition: "operation.type == 'delete'"
action: require_human_approval
target: dba-team@securight.au
timeout_seconds: 1800
Rule 3: Timeouts Must Be Bounded
Every tool invocation requires a finite timeout. The linter rejects missing or zero-value timeouts and warns on excessively high values.
Invalid configuration:
allowed_tools:
- name: long_running_analysis
permissions: [execute]
timeout_seconds: 0
max_retries: -1
Valid configuration:
allowed_tools:
- name: long_running_analysis
permissions: [execute]
timeout_seconds: 120
max_retries: 3
Rule 4: Data Classification Consistency
An agent's data classification level must be compatible with the tools it accesses. A public classification agent must not access tools that return protected data.
Invalid configuration:
spec:
data_classification: public
allowed_tools:
- name: patient_records_api
permissions: [read]
data_classification: highly_protected
Valid configuration:
spec:
data_classification: highly_protected
allowed_tools:
- name: patient_records_api
permissions: [read]
data_classification: highly_protected
Usage Guide
CLI Usage
The simplest way to run the linter is against a single policy file from the command line.
# Validate a single policy file
securight lint policy.yaml
# Validate all policies in a directory
securight lint ./policies/
# Validate with strict mode (warnings treated as errors)
securight lint --strict policy.yaml
# Output results as JSON for programmatic consumption
securight lint --format json policy.yaml
# Validate against a specific schema version
securight lint --schema-version v1.2 policy.yaml
# Dry-run a policy against a live agent configuration
securight lint --dry-run --agent invoice-processor policy.yaml
CI/CD Integration
The linter is designed to run as a step in your deployment pipeline. Below is an example GitHub Actions workflow.
# .github/workflows/policy-lint.yml
name: Agent Policy Lint
on:
pull_request:
paths:
- 'policies/**'
- 'agents/**/policy.yaml'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install SecuRight CLI
run: |
curl -fsSL https://cli.securight.au/install.sh | bash
securight --version
- name: Lint agent policies
run: |
securight lint --strict --format github-actions ./policies/
- name: Upload lint report
if: always()
uses: actions/upload-artifact@v4
with:
name: policy-lint-report
path: .securight/lint-report.json
Pre-Deployment Checks
For teams deploying agents through infrastructure-as-code, the linter can be invoked as a pre-deployment validation step.
# In a deployment script
echo "Validating agent policies..."
securight lint --strict --fail-on-warning ./deploy/policies/
if [ $? -ne 0 ]; then
echo "Policy validation failed. Deployment aborted."
exit 1
fi
echo "Policies validated. Proceeding with deployment."
securight deploy --config ./deploy/agent-config.yaml
Sample Output
When the linter identifies issues, it produces structured output categorised by severity. The following is an example run against a policy file containing several misconfigurations.
$ securight lint --strict ./policies/data-pipeline-agent.yaml
SecuRight Agent Policy Linter v2.4.1
Validating: ./policies/data-pipeline-agent.yaml
Schema version: securight/v1
ERRORS (2)
E001 line 14 Wildcard tool access is prohibited.
allowed_tools[0].name is set to "*".
Explicitly list each permitted tool with scoped permissions.
E007 line 31 Missing escalation rule for high-risk action.
Tool "database_admin" has [delete] permission but no
corresponding escalation_rules entry exists.
Add an escalation rule with trigger for delete operations.
WARNINGS (3)
W002 line 22 Timeout exceeds recommended maximum.
allowed_tools[2].timeout_seconds is 600 (max recommended: 300).
Consider breaking long operations into smaller tasks.
W005 line 8 Policy review overdue.
metadata.last_reviewed is "2025-09-10" (178 days ago).
Policies should be reviewed at least every 90 days.
W011 line 38 Human approval scope is broad.
human_approval_required[0].scope is "all".
Consider narrowing scope to reduce operator fatigue.
INFO (1)
I003 line 4 Environment set to "staging".
Staging policies are not enforced in production deployments.
Summary: 2 errors, 3 warnings, 1 info
Status: FAILED (--strict mode: warnings treated as errors)
Run `securight lint --fix ./policies/data-pipeline-agent.yaml` for auto-fix suggestions.
0 for pass, 1 for errors, and 2 for warnings when --strict is enabled. Use these codes in your pipeline logic to gate deployments appropriately.
Integration Patterns
The Agent Policy Linter fits into several points in a secure development lifecycle. The following patterns represent recommended integration strategies.
Git Hooks
A pre-commit hook ensures that no invalid policy is committed to the repository. This provides the fastest feedback loop for developers.
# .git/hooks/pre-commit
#!/bin/sh
POLICY_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(yaml|yml|json)$' | grep -i 'policy')
if [ -n "$POLICY_FILES" ]; then
echo "Linting modified agent policies..."
echo "$POLICY_FILES" | xargs securight lint --strict
if [ $? -ne 0 ]; then
echo "Commit rejected: policy lint errors found."
echo "Fix the issues above or use --no-verify to bypass (not recommended)."
exit 1
fi
fi
Pull Request Checks
Integrating the linter as a required PR check ensures peer review is informed by automated validation. The --format github-actions flag produces inline annotations directly in the PR diff, making issues visible at the exact line where they occur. Teams using Bitbucket or GitLab can use --format codeclimate for equivalent functionality.
Deployment Pipeline Gates
The strongest integration point is as a mandatory gate in your deployment pipeline. Place the linter after policy files are resolved (environment variables substituted, templates rendered) but before any agent is deployed or updated. This catches issues that may not be visible in the raw template — for example, an environment variable that resolves to a wildcard or an overly permissive default.
# Terraform-style deployment with policy gate
resource "securight_agent" "invoice_processor" {
name = "invoice-processing-agent"
policy = file("./policies/invoice-processor.yaml")
lifecycle {
precondition {
condition = securight_policy_lint.result.status == "passed"
error_message = "Agent policy failed lint validation."
}
}
}
Continuous Monitoring
Policies can drift from their intended state. Schedule the linter to run periodically against deployed agent configurations, not just at commit time. A weekly cron job that pulls active policies from your agent runtime and validates them against current schema versions catches staleness issues (like the W005 review-overdue warning) and ensures ongoing compliance with evolving organisational standards.
Policy validation is not a one-time gate. It is a continuous discipline. The best security teams lint at commit, at deploy, and on a schedule — because the threat landscape changes even when your code does not.