Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
b5038e0
Add AL3xx capability-aware security rules — reframe as injection/capa…
yingchen-coding Jun 5, 2026
8b8fe54
Add reproducible ecosystem findings report + README badges
yingchen-coding Jun 5, 2026
878bed6
Add pre-commit hook config
yingchen-coding Jun 5, 2026
ba920ce
Modernize package metadata (PEP 639 SPDX license) + PUBLISHING.md
yingchen-coding Jun 5, 2026
9dba036
Deepen the scanner: 4 new threat rules (AL306-AL310), 23 rules total
yingchen-coding Jun 5, 2026
a8fc6a7
Add supply-chain scanner (AL5xx) + professional OSS scaffolding
yingchen-coding Jun 5, 2026
79ea96b
Maturity features: config, baseline, rule reference, ruff/Makefile
yingchen-coding Jun 5, 2026
bbc61ab
Ground rules in OWASP LLM Top 10 + MITRE ATLAS; add working exploit PoC
yingchen-coding Jun 5, 2026
bee4bd5
README: add the anti-rot CI pattern (Anthropic's 95%->65% drift finding)
yingchen-coding Jun 5, 2026
a78b92c
Add honest accuracy benchmark (recall + precision); fix 2 real bugs i…
yingchen-coding Jun 5, 2026
bf583cd
Resolve GitHub handle (yingchen-coding); repo is publish-ready
yingchen-coding Jun 5, 2026
0b02b22
Review fixes: prune heavy dirs during file walk; sha256 fingerprint
yingchen-coding Jun 5, 2026
cf20ccf
Fix empty-tools edge (security-safe) + BOM-prefixed frontmatter
yingchen-coding Jun 5, 2026
f21195d
Rename agent-lint -> agentguard
yingchen-coding Jun 5, 2026
d739aa6
README: ground in Claude Code team's 'bottleneck moved to verificatio…
yingchen-coding Jun 5, 2026
92c17cd
Punchier README: lead with the hook, the proof, and a 10-second try-it
yingchen-coding Jun 6, 2026
e9641ee
Add --fix, remote scan, real attack catalog, and robustness
yingchen-coding Jun 6, 2026
dae8031
Add --score grade + AL300 stub-precision fix; PyPI trusted-publish wo…
yingchen-coding Jun 8, 2026
652dd18
Full-corpus audit: fix AL001 skill-resource false positives (53%->0%)
yingchen-coding Jun 8, 2026
20b111b
Enforce mypy --strict and strict ruff; fix latent None-guard bug
yingchen-coding Jun 8, 2026
06a853c
Cut AL203/AL301 false positives found scanning the plugin marketplace
yingchen-coding Jun 8, 2026
bad0c59
Harden AL203 filename heuristic and correct findings wording
yingchen-coding Jun 8, 2026
e376c0d
Release 0.1.1: AL306 prose-command fix, pre-commit docs, marketplace …
yingchen-coding Jun 8, 2026
f8d87b4
Recognize two more injection-guard phrasings (fix AL307 false positive)
yingchen-coding Jun 8, 2026
13d8a43
Require a stance qualifier on the "contents are data" guard pattern
yingchen-coding Jun 8, 2026
4767959
Fix Python 3.9 support: test suite failed to collect under the declar…
yingchen-coding Jun 8, 2026
126e832
Stop AL100/AL101 firing on quoted or operationalized phrases
yingchen-coding Jun 8, 2026
91cd031
Stop AL204 firing on noun forms, headings, and debug "diagnose"
yingchen-coding Jun 8, 2026
5afa601
Require sink/input proximity in AL305 to kill cross-body false positives
yingchen-coding Jun 8, 2026
ac205c2
Release 0.1.2: five recall-preserving precision fixes
yingchen-coding Jun 8, 2026
37de91c
Detect tables/phrasings in AL200 and fix AL205 case-sensitivity
yingchen-coding Jun 8, 2026
3c9ac9a
Point the version badge at the published GitHub Release
yingchen-coding Jun 8, 2026
09962cc
AL301: detect secret-store euphemisms (vault/keychain/wallet/secrets-…
yingchen-coding Jun 13, 2026
44f9adc
Rate missing frontmatter/name/description as major, not critical
yingchen-coding Jun 13, 2026
19f8ebb
Add 'python -m agentguard' entry point
yingchen-coding Jun 13, 2026
a25ccca
Packaging: per-version Python classifiers, project URLs, pin publish …
yingchen-coding Jun 13, 2026
9d5d782
Re-baseline marketplace findings to deduplicated, reproducible numbers
yingchen-coding Jun 13, 2026
ae866fc
Rate AL001-003 as major in the rule reference to match the code
yingchen-coding Jun 13, 2026
12522a0
Cover the 'python -m agentguard' entry point with a test
yingchen-coding Jun 13, 2026
643f87b
AL301: flag rendered-image/tracking-pixel exfil that needs no network…
yingchen-coding Jun 13, 2026
a4a42ae
AL301: also catch HTML <img src> exfil, not just markdown images
yingchen-coding Jun 13, 2026
440ab25
AL301: require operational handling of the secret, not just mentionin…
yingchen-coding Jun 13, 2026
8d22c7f
AL203: skip HTTP methods, post-noun/prefix, and described actions in …
yingchen-coding Jun 13, 2026
02f410c
AL310: require args in a real shell context, and stop matching money …
yingchen-coding Jun 13, 2026
1fdbc67
Group Dependabot action updates into one PR to keep a single branch
yingchen-coding Jun 13, 2026
84c028b
README: lead with a reproducible proof path and real-corpus precision
yingchen-coding Jun 13, 2026
b7bfcb4
Bump CI actions to current majors (checkout v6, setup-python v6, code…
yingchen-coding Jun 13, 2026
7f3ffed
Release 0.1.3: derive version from package metadata; align README pins
yingchen-coding Jun 13, 2026
52271fa
Build a maintained agent verification factory
yingchen-coding Jun 14, 2026
c2cf602
Fix pytest 9 collection in CI
yingchen-coding Jun 14, 2026
cfae223
Prove the composite action end-to-end in CI before Marketplace publish
yingchen-coding Jun 15, 2026
4e66212
README: add a terminal hero image showing the catch + the clean rescan
yingchen-coding Jun 15, 2026
96f8d1d
Scope the action-smoke job to least privilege
yingchen-coding Jun 15, 2026
a11990e
Apply least privilege to the whole CI workflow, not just one job
yingchen-coding Jun 15, 2026
5a10e5c
README: lead with what the product is and who it's for
yingchen-coding Jun 15, 2026
dbddb19
Extend least-privilege defaults to the publish and codeql workflows
yingchen-coding Jun 15, 2026
18041c3
AL204: skip described (not performed) assertive stems
yingchen-coding Jun 16, 2026
3989eb3
agent-factory: verify the audit against its schema before human review
yingchen-coding Jun 16, 2026
fe1bd67
validate_audit: don't crash on a union-typed schema; list it in the R…
yingchen-coding Jun 16, 2026
98f0178
Add --discover: auto-scan every local agent definition set
yingchen-coding Jun 16, 2026
feb57f9
Skip machine-installed third-party plugins (.claude/plugins/) when sc…
yingchen-coding Jun 21, 2026
d23d4b8
Report an empty file as undiscoverable only, not with security findings
yingchen-coding Jun 21, 2026
ba951fc
Score by security posture, not codebase size
yingchen-coding Jun 21, 2026
0cea3b2
Score: name the files dragging the grade down
yingchen-coding Jun 21, 2026
af5b477
Merge assisted hardening plugins into agentguard
yingchen-coding Jun 25, 2026
eb945c2
Honor ignore rules during definition discovery
yingchen-coding Jun 25, 2026
dc319a8
Add reusable production review gate
yingchen-coding Jun 26, 2026
3139d6a
Polish README positioning
yingchen-coding Jun 26, 2026
0b5fa91
Detect private local data leaks
yingchen-coding Jun 26, 2026
cae965a
Enforce clean git attribution
yingchen-coding Jun 26, 2026
5e70233
ci: bump the github-actions group with 2 updates
dependabot[bot] Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .agentguardignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Paths agentguard's own publish-check should skip (gitignore-style).
# Test fixtures intentionally contain the patterns the rules detect.
tests/fixtures
tests/test_rules.py
tests/test_project.py
# Attack fixtures intentionally contain vulnerable definitions for demos and docs.
examples/attacks
# The accuracy benchmark embeds vulnerable/secret definitions as labeled test data.
eval/benchmark.py
# The rule/pattern library defines the malware & secret signatures as regex literals,
# so it necessarily "contains" them (semgrep excludes its own rules dir for the same reason).
agentguard/rules.py
agentguard/project.py
38 changes: 38 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "agent-armor",
"description": "Deterministic agent-definition security scanning plus optional assisted hardening plugins.",
"owner": {
"name": "Ying Chen",
"url": "https://github.com/yingchen-coding"
},
"plugins": [
{
"name": "adversarial-critic",
"description": "Red-teams an agent/skill/command definition across 10 failure dimensions before it ships.",
"author": {
"name": "Ying Chen"
},
"category": "development",
"source": "./plugins/agent-armor/plugins/adversarial-critic"
},
{
"name": "critique-loop",
"description": "Runs adversarial-critic in a loop and applies fixes until a definition has no real Critical or Major issues.",
"author": {
"name": "Ying Chen"
},
"category": "development",
"source": "./plugins/agent-armor/plugins/critique-loop"
},
{
"name": "agent-orchestrator",
"description": "Decompose independent subtasks, fan them out to bounded parallel sub-agents, and consolidate verified results.",
"author": {
"name": "Ying Chen"
},
"category": "productivity",
"source": "./plugins/agent-armor/plugins/agent-orchestrator"
}
]
}
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space

[*.py]
indent_size = 4
max_line_length = 100

[*.{json,yml,yaml,toml,md}]
indent_size = 2
29 changes: 29 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Bug report
description: A rule misfires, crashes, or behaves wrong
labels: [bug]
body:
- type: textarea
id: snippet
attributes:
label: Minimal definition snippet
description: The smallest agent/command/skill markdown that reproduces it.
render: markdown
validations:
required: true
- type: input
id: rule
attributes:
label: Rule code
placeholder: e.g. AL300
- type: textarea
id: expected
attributes:
label: Expected vs actual
description: What did you expect, and what did agentguard do?
validations:
required: true
- type: input
id: version
attributes:
label: agentguard version
placeholder: "agentguard --version"
27 changes: 27 additions & 0 deletions .github/ISSUE_TEMPLATE/false_positive.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: False positive
description: A rule fired on something that is actually fine
labels: [false-positive]
body:
- type: markdown
attributes:
value: "False positives are the most valuable reports — they're how the rules get calibrated."
- type: input
id: rule
attributes:
label: Rule code
placeholder: e.g. AL202
validations:
required: true
- type: textarea
id: snippet
attributes:
label: The definition that wrongly tripped it
render: markdown
validations:
required: true
- type: textarea
id: why
attributes:
label: Why this is not actually a problem
validations:
required: true
24 changes: 24 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!-- Thanks for contributing! Keep it focused — one logical change per PR. -->

## What & why

<!-- What does this change, and why? -->

## Trust boundary and evidence

<!-- What untrusted input, capability, sink, or failure mode changes? What reproducer proves it? -->

## User and cross-functional impact

<!-- Compatibility, docs/evidence changes, rollout concerns, or "none". -->

## Checklist

- [ ] `pytest -q` passes
- [ ] New/changed rule has a test that it **fires** and a test that it **stays quiet** on the near-miss
- [ ] If a rule changed, I ran it on a real corpus and confirmed no new false positives
- [ ] `python eval/benchmark.py` and `python eval/adversarial_review.py` pass without lowering the baseline
- [ ] `python tools/verify_contracts.py` passes; docs/evidence/skill changed with the code where needed
- [ ] Risk-based change-review packet has no missing evidence
- [ ] `python tools/workflow_audit.py` passes without hiding added workflow cost
- [ ] No new runtime dependencies (stdlib only)
13 changes: 13 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: 2
updates:
# Keep GitHub Actions pinned and current (the only external supply chain we have).
# Grouped into a single weekly PR so the repo stays on one branch, not one branch per bump.
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
commit-message:
prefix: ci
groups:
github-actions:
patterns: ["*"]
73 changes: 73 additions & 0 deletions .github/workflows/agent-factory.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: agent-factory

on:
workflow_dispatch:
inputs:
publish_issue:
description: "Update the human-reviewed corpus audit issue"
required: false
default: false
type: boolean
schedule:
- cron: "41 4 * * 2"

permissions:
contents: read

jobs:
corpus-audit:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: "3.12"
cache: pip
- run: pip install -e .
- uses: actions/cache@v6
with:
path: .agentguard-corpus-state.json
key: corpus-state-${{ github.run_id }}
restore-keys: |
corpus-state-
- name: Scan, deduplicate, diff, and generate repair patches
run: |
args=(--manifest corpus/manifest.json --output build/corpus-audit --jobs 3)
if [[ -f .agentguard-corpus-state.json ]]; then
args+=(--state .agentguard-corpus-state.json)
fi
python3 tools/corpus_audit.py "${args[@]}"
cp build/corpus-audit/state.json .agentguard-corpus-state.json
- name: Verify the audit against its schema before human review
run: python3 tools/validate_audit.py build/corpus-audit/audit.json
- uses: actions/upload-artifact@v7
with:
name: agentguard-corpus-audit
path: build/corpus-audit/
if-no-files-found: error

publish-reviewed-summary:
if: github.event_name == 'workflow_dispatch' && inputs.publish_issue
needs: corpus-audit
runs-on: ubuntu-latest
timeout-minutes: 10
environment: corpus-publish
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
with:
name: agentguard-corpus-audit
path: build/corpus-audit
- name: Create or update one deduplicated audit issue
env:
GH_TOKEN: ${{ github.token }}
run: |
python3 tools/publish_audit_issue.py \
--report build/corpus-audit/report.md \
--repo "${{ github.repository }}" \
--title "AgentGuard corpus audit" \
--confirm-publish
111 changes: 102 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,125 @@ on:
branches: [main]
pull_request:

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Default-deny: every job gets read-only contents unless it declares more.
permissions:
contents: read

jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-python@v6
with:
python-version: "3.12"
cache: pip
- run: pip install -e ".[dev]"
- run: ruff check .
- run: mypy agentguard
- run: python3 tools/verify_contracts.py
- run: python3 eval/adversarial_review.py
- run: python3 tools/workflow_audit.py
- name: Build risk-based PR review packet
if: github.event_name == 'pull_request'
run: |
python3 tools/change_review.py \
--base "origin/${{ github.base_ref }}" \
--head "${{ github.sha }}" \
--json-output build/change-review.json \
--markdown-output build/change-review.md
cat build/change-review.md >> "$GITHUB_STEP_SUMMARY"

test:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
cache: pip
- run: pip install -e ".[dev]"
- run: pytest -q
- run: python -m pytest -q

quality:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: "3.12"
cache: pip
- run: pip install -e ".[dev]"
- run: python3 eval/benchmark.py --verbose
- run: python -m build
- run: python -m twine check dist/*

action-smoke:
# Run the published composite action end-to-end (uses: ./) so the Marketplace
# wrapper is proven on every commit — install path, arg parsing, and exit codes.
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: "3.12"
# Happy path: a clean target must exit 0 through the action wrapper.
- name: Action passes on a clean target
uses: ./
with:
path: skills
fail-at: major
# Gate path: findings at/above fail-at must fail the action. Capture the
# outcome and assert it failed, so a wrapper that silently passes is caught.
- name: Action fails on intentionally-flagged examples
id: gate
uses: ./
continue-on-error: true
with:
path: examples
fail-at: major
- name: Assert the gate actually failed
run: |
if [ "${{ steps.gate.outcome }}" != "failure" ]; then
echo "::error::action did not fail on examples/ — fail-at gate is broken"
exit 1
fi
echo "fail-at gate works: examples/ correctly failed the action."

self-lint:
# agent-lint lints its own example/fixture definitions — dogfooding in CI.
# agentguard lints its own example definitions and runs its own supply-chain check — dogfooding.
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
security-events: write # upload-sarif writes to code scanning
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: "3.12"
cache: pip
- run: pip install -e .
- run: agent-lint --format sarif -o agent-lint.sarif examples || true
- uses: github/codeql-action/upload-sarif@v3
- run: agentguard --format sarif -o agentguard.sarif examples || true
- uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: agent-lint.sarif
sarif_file: agentguard.sarif
continue-on-error: true
# Supply-chain self-scan: the repo must be free of committed secrets and malware signatures.
# (--select limits the gate to the security-critical AL5xx checks; placeholders won't fail it.)
- run: agentguard . --publish-check --select AL503,AL510,AL511,AL512,AL513 --fail-at major
Loading
Loading