Introduction: AI features ship fast, governance arrives late
Most teams don't start their AI journey with a governance plan -- they start with a demo. They wire in an LLM SDK, add some RAG, experiment with tools and agents, and only later realize that sensitive data, unapproved calls, and missing audit trails are scattered across the codebase.
By that point, AI features are in production or close to it, and it's hard to answer basic questions like:
- Where do we send PII or PHI in prompts?
- Which files call providers like OpenAI or Anthropic directly without going through our gateway?
- Which tools and agents can take risky actions without approval or budget limits?
- Where does RAG return answers without citations or grounding checks?
- How much of our LLM usage is actually covered by our policies and audit requirements?
PolicyAware exists to make those questions answerable. It's an open-source, policy-aware AI gateway and governance framework for LLM, RAG, MCP/tool, and AI-agent applications, with a CLI and Python API you can run locally in your own environment.
This article focuses on one capability: local code scanning with policyaware scan, which helps detect AI governance gaps in your repository without calling models or external services.
What policyaware scan actually does
policyaware scan is a fast, local governance and compliance scanner for AI application repositories. It scans source code, policy files, notebooks, infrastructure configuration, and data pipeline code for risks that matter in LLM, RAG, MCP/tool, and agent-based systems.
Important design choices:
- It does not call external services.
- It does not call models.
- It does not execute your project code.
You can run it safely on a laptop, CI runner, or secure build agent without changing how your application behaves.
Governance areas it checks
The scanner looks for issues across multiple AI-specific governance categories, including:
- PII: prompts or config containing emails, phone numbers, SSNs, or credit-card-like values that should be redacted before reaching models, tools, logs, or evaluators.
- PHI: patient identifiers, medical record language, diagnosis or prescription text that may require regulated-domain policies and redaction.
- Secrets: hardcoded API keys, tokens, bearer tokens, and secret assignments that should be moved into secret managers or environment variables and rotated.
- Direct LLM calls: direct usage of SDKs and frameworks such as OpenAI, Anthropic, Bedrock, Vertex AI, LiteLLM, Ollama, LlamaIndex, DSPy, and Semantic Kernel that bypass the PolicyAware gateway routing.
- Provider governance gaps: model and provider usage that isn't routed by approved provider, role, risk level, region, cost, or availability policy.
- MCP/tool governance risks: function calls, LangChain tools, MCP connectors, and other tools that can take impactful actions without connector or action policies and approval requirements.
-
Autonomous agent risks: patterns like
while True,agent.run, or auto-execution loops that don't enforce human approval, max iterations, budgets, or audit logging. - RAG grounding and citation gaps: retrieval, vector store and embedding usage where responses are not tied to sources, metadata, or citation checks.
- Data residency concerns: external endpoints, regions, API bases, and cloud locations that may move regulated data outside approved boundaries without tenant or region constraints.
- Cost governance gaps: model or agent calls without clear token, timeout, rate, retry, or budget limits at request and workflow levels.
-
YAML policy quality: policy schema errors and missing
default: denyrules that weaken deny-by-default behavior. -
Configuration governance:
.env, YAML, JSON, Terraform, Docker, CI/CD files that hold credentials or sensitive values instead of secret manager references. - Audit gaps: model and tool calls that lack trace/audit language, making it harder to reconstruct decisions, routes, evaluation results, and response metadata later.
From a platform or security perspective, this helps teams see AI-specific risks that traditional SAST or generic secret scanners often miss, especially around RAG behavior, tool orchestration, agent loops, and policy coverage.
Installation
PolicyAware is published on PyPI, so you can install it like any other Python tool:
pip install policyaware
If you're working directly from the PolicyAware repository, there's also a development install option documented in the wiki, but for most enterprise users pip install policyaware is enough to get started with the CLI.
Quick start: scan a local folder and open the HTML report
To run a basic local scan against an AI application folder:
policyaware scan ./mylocalfolder
By default, this generates an HTML report:
policyaware-scan-report.html
You can tell the CLI to open the report automatically in your browser:
policyaware scan ./mylocalfolder --open
This is a good "first touch" workflow:
- Run the scan against a sample or production-like project.
- Open the HTML report.
- Review the executive summary and severity counts.
- Click into the findings by file and category to see what the scanner is actually flagging.
For AI platform, security, and compliance engineers, this is a low-friction way to surface governance issues without introducing latency into production traffic or forcing teams to adopt a full gateway orchestration on day one.
Multiple report formats for humans, CI, and automation
policyaware scan supports multiple output formats so you can serve developers, reviewers, and automated workflows with the same scan:
policyaware scan . --format html,json,sarif,markdown
Here's how those formats are typically used:
- HTML: for humans -- developers, policy engineers, security reviewers, and compliance teams reviewing findings, remediation recommendations, and coverage.
- JSON: for automation -- pipelines that push findings into internal dashboards, ticketing systems, or governance workflows.
- SARIF: for GitHub code scanning and similar platforms that understand SARIF and can show findings inline in pull requests and repository views.
- Markdown: for review notes, compliance summaries, and documentation PRs where you want to include finding lists and remediation checklists in plain text.
In practice, teams often generate all four formats in CI and let different personas consume whichever format fits their workflow.
CI usage: fail builds on high-risk AI governance gaps
You can use policyaware scan in CI to enforce a minimum governance bar before merging AI changes. For example, failing the pipeline when the scan finds high-severity issues:
policyaware scan . --fail-on high
A GitHub Actions workflow that wires this into pull requests and pushes to main looks like this:
name: PolicyAware Scan
on:
pull_request:
push:
branches: [main]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install PolicyAware
run: python -m pip install policyaware
- name: Run scan
run: policyaware scan . --format html,json,sarif,markdown --fail-on high
This setup supports governance review by catching high-risk PII, PHI, secrets, LLM routing gaps, unapproved tools, and agent risks before they land in main, while still letting lower-severity findings through for future remediation.
Example findings PolicyAware Scan can flag
To make this concrete, here are some example patterns the scanner can flag in an LLM/RAG/agent repository:
-
Hardcoded API keys: secrets like
OPENAI_API_KEY = "sk_live_..."or bearer tokens in Python, JS, YAML, or.envfiles. - Prompts containing PII: system or user prompts that include email addresses or phone numbers, especially in templates reused across multiple flows.
- Direct OpenAI or Anthropic SDK calls: imports and calls to provider SDKs where requests bypass the PolicyAware gateway and its routing policies.
- LangChain tools without an approval policy: tool definitions that can make HTTP calls, read/write files, or trigger external systems without connector or action policies.
- RAG response paths without citation checks: retrieval and response code that surfaces answers to users without verifying sources or enforcing citation formatting.
-
Agent loops without budgets or max iterations:
while Trueloops or agent-run patterns that can incur unbounded cost or perform repeated, unreviewed actions. - Missing audit traces: model or tool calls where no logging, tracing, or audit metadata is attached, making investigations and compliance reviews harder.
-
YAML policies without
default: deny: policy files that allow actions by default instead of requiring explicit allow rules, which can weaken your governance posture.
Each finding in the HTML report includes redacted evidence and suggested remediation, so developers can see what triggered the finding and how to address it without exposing sensitive values in the report itself.
Why the HTML report matters for developers and reviewers
The HTML report is designed to be readable by both engineers and governance stakeholders. It includes:
- Executive summary and overall risk.
- Severity counts and finding categories.
- Compliance area counts and compliance-area filters.
- Top recommendations and remediation checklist.
- Findings grouped by file, with redacted evidence and suggested fix snippets.
- Guardrails orchestration findings and policy coverage score.
- Governance reviewer summary and links to documentation.
This makes it possible for:
- AI platform engineers to triage findings and prioritize fixes across services.
- Security engineers to focus on secrets, provider routing, and guardrails.
- Compliance engineers to map findings to frameworks like SOC 2 or internal AI governance standards.
- Enterprise architects to see where policies are enforced versus where they're missing.
Instead of handing someone a raw JSON or SARIF file, you can share a single HTML report that surfaces the most important issues and gives teams a structured remediation path.
Python API: use LocalCodeScanner directly
If you prefer to control scanning from Python instead of the CLI, PolicyAware exposes a LocalCodeScanner and ScanConfig class you can use from your own scripts or orchestration tools:
from pathlib import Path
from policyaware import LocalCodeScanner, ScanConfig
config = ScanConfig.from_file(Path("examples/policyaware-scan.yaml"))
report = LocalCodeScanner(workers=4, config=config).scan(
Path("."),
out=Path("policyaware-scan-report.html"),
json_out=Path("policyaware-scan-report.json"),
sarif_out=Path("policyaware-scan-report.sarif"),
markdown_out=Path("policyaware-scan-report.md"),
)
print(report.overall_risk)
print(report.category_counts)
print(report.compliance_counts)
This pattern lets you:
- Embed scans into internal tooling or developer portals.
- Customize concurrency (
workers) and configuration. - Generate multiple report formats in one call.
- Programmatically inspect
overall_risk, category counts, and compliance counts to drive additional automation.
Example scan config YAML
You can customize what policyaware scan looks at and which categories it enables by adding a YAML scan configuration file. A simple example looks like this:
scan:
include_extensions:
- .py
- .yaml
- .json
- .ipynb
- .tf
exclude_dirs:
- tests/fixtures
- generated
enabled_categories:
- PII
- PHI
- Secrets
- LLM Governance
- MCP/Tool Governance
- RAG Governance
- Guardrails Integration
- Audit Gaps
- Configuration Governance
max_file_size: 1mb
max_findings_per_file: 30
This configuration focuses the scanner on Python, notebook, config, and Terraform files, skips fixtures and generated content, and enables governance categories that matter for many enterprise AI applications. You can tune this for your environment, including severity overrides, disabled categories, ignore patterns, and baselines as documented in the Local Code Scan wiki page.
Where PolicyAware Scan fits relative to SAST and security scanners
PolicyAware Scan is not a replacement for SAST tools, generic secret scanners, or cloud security platforms, and it does not guarantee compliance or replace full security review. Instead, it focuses specifically on AI governance and LLM application risks.
A practical way to think about it:
| Tool type | Primary focus |
|---|---|
| SAST | General code vulnerabilities (injections, unsafe APIs, insecure patterns). |
| Secret scanners | Credentials and tokens in code, config, and history. |
| Cloud security tools | Infrastructure misconfigurations, network exposure, IAM policies, runtime drift. |
| PolicyAware Scan | AI governance gaps around LLMs, RAG, tools, agents, policies, audit, and compliance. |
In other words:
- Keep using SAST for core application security.
- Keep using secret scanners and cloud security tools for infrastructure, dependencies, and credentials.
- Use PolicyAware Scan to add an AI governance lens across your AI-specific code, policies, and orchestration.
This layered approach gives platform and security teams better coverage without overclaiming what any single tool can do.
Links and further reading
If you want to go deeper or integrate this into your own platform, the key links are:
- PyPI: https://pypi.org/project/policyaware/
- GitHub: https://github.com/ktirupati/policyaware
- Docs: https://ktirupati.github.io/policyaware/
- Local Code Scan Wiki: https://github.com/ktirupati/policyaware/wiki/Local-Code-Scan
These include additional examples, ready-to-use YAML templates, CLI reference, and governance guidance for LLM, RAG, tools, agents, and audit.
Closing
Local governance scanning won't solve every AI risk in one shot, but it does give your team visibility into where sensitive data, provider calls, tools, agents, and policies show up in the code -- and where your current governance posture has gaps.
Try it on a local AI app, open the HTML report, and fix the highest-risk governance gaps first.
Top comments (0)