Policies | Install | Usage | Custom policies | CI
- Features
- Example
- Installation
- Usage
- Output
- Ignoring files
- Policies
- Custom policies
- CI integration
- Troubleshooting
- agent-focused: built to scan Skills, Commands, Agent specs, and
AGENT.md/CLAUDE.mdfiles - OPA-powered: policies are plain Rego — readable, testable, and composable
- extensible: drop in any Git-hosted or local policy repository with one command
- CI-ready: exits
1on violations,0on clean — binary, container, orgo install - multi-platform container:
linux/amd64andlinux/arm64images onghcr.io, built on Chainguard
oy repo add github.com/aljoshare/oy-policies
# Scan all Skills and Commands
oy scan .claude/
# Scan root-level agent instruction files
oy scan CLAUDE.md
oy scan AGENT.mdOutput when violations are found:
FAIL .claude/skills/assistant/SKILL.md
- possible prompt injection: "ignore previous instructions"
- tool invocation abuse: bash tool
2 file(s) scanned, 2 violation(s) found
Install script (Linux and macOS)
curl -fsSL https://raw.githubusercontent.com/aljoshare/oy/main/install.sh | shInstalls the latest release to /usr/local/bin. To choose a different directory or pin a version:
# Install to ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/aljoshare/oy/main/install.sh | sh -s -- -b ~/.local/bin
# Pin to a specific version
curl -fsSL https://raw.githubusercontent.com/aljoshare/oy/main/install.sh | sh -s -- v1.2.0The script detects your OS and architecture, downloads the matching archive from GitHub Releases, verifies the SHA-256 checksum, and extracts the binary.
Container (recommended for CI)
nerdctl pull ghcr.io/aljoshare/oy:latestSupports linux/amd64 and linux/arm64. Built on Chainguard — minimal attack surface, runs as nonroot.
Go install
go install github.com/aljoshare/oy@latestBuild from source
git clone https://github.com/aljoshare/oy
cd oy
go build -o oy .Requirements (binary only): Go 1.21+, git (used by oy repo add to clone policy repos).
oy scan <path><path> can be a single .md file or a directory. Directories are walked recursively — so pointing oy at .claude/ scans all Skills and Commands in one shot.
# Scan all Skills and Commands under .claude/
oy scan .claude/
# Scan a single CLAUDE.md or AGENT.md
oy scan CLAUDE.md
# Use a local policy directory instead of registered repos
oy scan .claude/ --policies ./my-policies
# Output as JSON (useful for CI / downstream tooling)
oy scan .claude/ --format json| Flag | Short | Default | Description |
|---|---|---|---|
--policies |
-p |
— | Directory of .rego files to use instead of registered repos |
--format |
-f |
text |
Output format: text or json |
| Exit code | Meaning |
|---|---|
0 |
No violations found |
1 |
One or more violations found (or a fatal error occurred) |
oy listLists every rule that is active in the loaded policy set, sorted alphabetically. Rules without a # METADATA title are excluded — oy will also print a warning to stderr for each such rule when scanning.
# List rules from a local policy directory
oy list --policies ./my-policies
# Output as JSON
oy list --format jsonExample output:
- Data Exfiltration Instructions
Detects instructions to read sensitive files (SSH keys, AWS credentials, .env) and transmit them via HTTP, DNS, or image URLs.
- Instruction Override
Detects indirect prompt injection via instruction override patterns such as "ignore previous instructions" or "admin mode activated".
...
14 rule(s) loaded
| Flag | Short | Default | Description |
|---|---|---|---|
--policies |
-p |
— | Directory of .rego files to use instead of registered repos |
--format |
-f |
text |
Output format: text or json |
# Register a policy repository (cloned into the OS cache directory)
oy repo add github.com/aljoshare/oy-policies
# Pin to a specific tag or branch
oy repo add github.com/aljoshare/oy-policies@v1.2.0
# List registered repositories and their local cache paths
oy repo listoy repo add accepts bare host/owner/repo references as well as full https:// and git@ URLs. Append @ref to pin to a specific tag or branch — the repository is cloned with --depth=1 --branch <ref> so only that ref is fetched. Without @ref, the default branch is cloned.
Config is stored in your OS user config directory (~/.config/oy/config.json on Linux, ~/Library/Application Support/oy/config.json on macOS).
To update a registered repository, run git pull in its cache directory, which oy repo list will show you. Pinned refs do not need updating — re-add with a new @ref to switch versions.
Text (default) — violations found
FAIL .claude/skills/assistant/SKILL.md
- possible prompt injection: "ignore previous instructions"
- potentially destructive shell command: "rm -rf /"
2 file(s) scanned, 2 violation(s) found
Text — clean
OK: 3 file(s) scanned, no violations found
JSON
{
"files_scanned": 2,
"violations": [
{
"file": ".claude/skills/assistant/SKILL.md",
"message": "possible prompt injection: \"ignore previous instructions\""
}
]
}Create a .oyignore file in the root directory being scanned to exclude files from evaluation. Patterns follow the same syntax as filepath.Match — glob wildcards are supported, and lines starting with # are treated as comments.
# .oyignore
vendor/AGENT.md
*.generated.md
docs/*.md
Files matched by .oyignore are skipped silently. If all files in a directory are ignored, oy scan exits 0 with no output.
Policies are maintained in separate repositories and registered with oy repo add. The official collection is aljoshare/oy-policies:
| Policy file | Detects |
|---|---|
prompt_injection.rego |
Instruction overrides, context/memory poisoning, invisible Unicode injection |
jailbreak.rego |
DAN/AIM/BISH/STAN personas, safety bypass framing, hypothetical/fictional framing, FlipAttack |
harmful_commands.rego |
Destructive shell commands, privilege escalation, persistence attacks, supply chain attacks |
exfiltration.rego |
Sensitive file reads, credential/key exposure, env var dumping, pipe-to-shell, image-URL exfiltration |
social_engineering.rego |
Phishing patterns, agent-targeted urgency/authority framing, false-context misdirection |
tool_poisoning.rego |
Tool/skill invocation abuse, MCP tool poisoning via hidden HTML comments |
See the oy-policies repository for full descriptions and source citations.
Policies are plain Rego files. All rules must belong to package oy and express violations as deny set entries. Each rule must have a # METADATA block with at least a title — rules without one are skipped during scanning and a warning is printed to stderr.
package oy
import rego.v1
# METADATA
# title: My Custom Rule
# description: Detects my forbidden phrase in agent files.
deny contains msg if {
contains(lower(input.content), "my forbidden phrase")
msg := "found forbidden phrase"
}Input available to every rule:
| Field | Type | Description |
|---|---|---|
input.path |
string |
Path to the scanned file |
input.content |
string |
Full file content |
input.lines |
array<string> |
Content split by newline |
Using a local directory
oy scan .claude/ --policies ./my-policiesUsing a Git-hosted repository
oy repo add github.com/myorg/my-oy-policies
oy scan .claude/oy exits with code 1 when violations are found, making it a drop-in gate in any pipeline. Pin to a specific version tag in production for reproducible results.
GitHub Actions — action (recommended)
- uses: aljoshare/oy-action@v1
with:
path: .claude/
- uses: aljoshare/oy-action@v1
with:
path: CLAUDE.mdThe official policy collection is cloned automatically. See aljoshare/oy-action for the full input reference.
GitLab CI
scan-agent-files:
image: ghcr.io/aljoshare/oy:v0.1.0
variables:
GIT_STRATEGY: clone
before_script:
- git clone https://github.com/aljoshare/oy-policies.git
script:
- oy scan .claude/ --policies ./oy-policies
- oy scan CLAUDE.md AGENT.md --policies ./oy-policiesGitHub Actions — binary
- name: Scan agent files for malicious instructions
run: |
go install github.com/aljoshare/oy@v0.1.0
oy repo add github.com/aljoshare/oy-policies
oy scan .claude/
oy scan CLAUDE.md AGENT.mdno policy repositories configured
No repos registered yet. Run oy repo add github.com/aljoshare/oy-policies.
cloning "...": ...
git is not installed or the URL is unreachable. Verify git is in your PATH.
no .rego files found
The directory passed to --policies contains no .rego files, or a registered repository cache is empty. Run oy repo list to check local paths.
scanning "...": ...
The path passed to oy scan does not exist or is not readable.
