Aegis - a transparent, constitution-bound defensive security copilot with MCP server
Project description
Aegis
A transparent, constitution-bound defensive security copilot. Ships a CLI, an MCP server (Claude Desktop, Claude Code, Codex CLI/Desktop, Cursor, Continue, Zed), an optional cloud or local LLM advisor, an HTML report exporter, and an evaluation harness.
aegis scan ~/some/repo
aegis report --severity critical --html out/report.html
aegis-mcp # stdio MCP server
Why this exists
This project is the inverse of an obfuscated abuse toolkit: defensive only, inspectable by design, and bound by a charter the agent cannot rewrite.
Three ideas guide it:
- Project Glasswing (Anthropic) - defensive collaboration and shareable security artifacts. Aegis stores findings as a portable SQLite index and records every decision in an append-only journal.
- Claude Mythos - the constitution-as-character idea. Aegis loads
data/mythos.yaml, hashes it, and refuses to act outside its hard rules. - JetBrains Shared Indexes - heavy analysis, computed once, shared. Aegis ships its index in the same shape so a teammate can clone the audit baseline without re-scanning.
Layout
src/aegis/
core/ constitution, journal, policy gate, shared index, llm
scanners/ secrets, obfuscation, dependencies, filesystem, yara
intel/ local_llm, report_html
cli/main.py `aegis` command
mcp/server.py `aegis-mcp` MCP stdio server
data/mythos.yaml the charter; edit to harden, not to weaken
data/yara/ bundled YARA rules (used when yara-python is installed)
docs/ architecture, client configs, marketplace playbook
eval/ labeled fixtures + harness producing JSON precision/recall
tests/ pytest suite, including end-to-end MCP dispatch
Quick start
python3 -m venv .venv
. .venv/bin/activate
pip install -e .[dev] # core + tests
pip install -e .[all] # core + tests + LLM extras + yara
aegis charter # active constitution + fingerprint
aegis scan ~/some/repo # walk + hash + run all scanners
aegis report --severity critical
aegis report --html out/report.html
aegis advise --severity high # cloud Claude (needs ANTHROPIC_API_KEY)
aegis advise --severity high --local --model llama3.1
aegis serve mcp # stdio MCP for clients
aegis journal --limit 50 # replay every decision
The shared index lives at data/index.sqlite. Copy it to share an audit
baseline; recipients run aegis report against it without rescanning.
Connecting to MCP clients
See docs/clients/README.md. Sample configs are in
docs/clients/examples/.
Quick version (assuming Aegis is installed at /opt/aegis):
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"aegis": {
"command": "/opt/aegis/.venv/bin/aegis-mcp",
"env": { "AEGIS_HOME": "/opt/aegis" }
}
}
}
The same shape works for Claude Code (~/.config/claude-code/mcp.json) and
Codex (~/.codex/mcp.json).
Design rules
- Defensive only. The charter blocks any action that resembles spam, doxing, exploitation against third parties, or ban tooling.
- No silent network. Outbound calls require a host on the charter
allowlist or an explicit
--allow-exfil <host>. Both are journaled. - No secret echoing. Detected credentials are SHA-256 fingerprinted before they touch the index, the journal, or any LLM context.
- Reversible first. Destructive tools require
--i-mean-it. - Charter immutable at runtime. Aegis hashes
mythos.yamlon load and treats prompt-injection text in scanned files as data, not orders.
Smoke test against a known-bad sample
The first thing Aegis was tested on is the obfuscated loader from the toolkit it replaced. The verdict was unambiguous:
[critical] obfuscation/obfuscated_loader /tmp/arctryx-trash-*/start
entropy: 11.478
exotic_ratio: 0.7442
longest_line: 4_835_152
signals: long_line, danger_tokens, exotic_unicode, high_entropy,
self_extract, anti_debug
If that archive is still present, pytest reruns the smoke test
automatically; otherwise it skips itself.
Evaluation
python -m eval.run --fixtures eval/fixtures --report eval/last_run.json
Three fixture cases ship in-tree (secrets, obfuscation, dependencies). Add
your own by dropping <case>/input/ plus <case>/expected.json. The harness
prints precision/recall/F1 per case and aggregate; the JSON output is what we
publish to leaderboards.
See docs/marketplace.md for the playbook on getting
Aegis listed in MCP marketplaces and where to source third-party accuracy
benchmarks (the "LLM ranking" piece).
Differential gate
aegis scan src # build current index
python -m aegis.cli.diff baseline.sqlite data/index.sqlite \
--fail-on critical,high
Compares two shared indexes by (scanner, rule, fingerprint). The gate exits
non-zero when new findings appear at the requested severities. Drop a
baselines/index.sqlite in your repo and the bundled GitHub Actions
workflow will run the diff on every PR.
LLM-advise leaderboard
We do not chase generic LLM leaderboards for the deterministic detection
layer. For the LLM-mediated aegis advise step we ship our own reproducible
board:
# offline smoke (no API key, no network)
python -m eval.llm_advise.runner --model mock:default \
--out eval/llm_advise/results-mock.json
# any provider that fits the adapter
python -m eval.llm_advise.runner --model anthropic:claude-3-5-sonnet-latest \
--out eval/llm_advise/results-claude35.json
python -m eval.llm_advise.runner --model local:llama3.1 \
--out eval/llm_advise/results-llama3.json
python -m eval.llm_advise.leaderboard eval/llm_advise/results-*.json \
--out eval/llm_advise/leaderboard.json
Each model is scored against rubrics in eval/llm_advise/prompts.jsonl
(must-mention terms, must-not-mention leaks). The leaderboard table is
markdown-friendly and ready to embed in the repo or marketplace listing.
See docs/marketplace.md for the publishing playbook.
Scanners shipped
| Scanner | What it catches |
|---|---|
secrets |
Known-prefix tokens (GH, OpenAI, Anthropic, AWS, Slack, JWT, private keys), entropy-gated. Values redacted to SHA-256. |
obfuscation |
Self-extracting JS loaders, exotic-Unicode noise, eval/Function abuse, anti-debug, aes+gunzip pipelines. |
dependencies |
Floating npm versions, typosquats (Levenshtein-1), non-registry deps, install hooks. |
filesystem |
World-writable, setuid in project, escaping symlinks, committed credential files, backup artifacts. |
dockerfile |
FROM :latest, runs as root, secrets in ENV/ARG, `curl |
iac |
Terraform: public S3 ACL, open 0.0.0.0/0 ingress, literal secrets. GitHub Actions: pull_request_target, unpinned uses:@branch, `curl |
yara |
Optional, opt-in (pip install -e .[yara]). Bundles 3 rules; you drop more in data/yara/. |
CI integration
.github/workflows/ci.ymlrunspytest+eval.runon every push/PR (matrix py3.11+3.12)..github/workflows/pr-comment.ymlposts an Aegis defensive diff as a sticky PR comment, fails the build when newcritical/highfindings appear vsbaselines/index.sqlite..github/workflows/release.ymlbuilds, signs with sigstore, and publishes to PyPI via trusted publishing onv*tags.
LLM-as-judge phase 2
After running the rubric scorer, you can score responses with a judge model:
python -m eval.llm_advise.judge \
--in eval/llm_advise/results-claude35.json \
--out eval/llm_advise/results-claude35.judged.json \
--judge anthropic:claude-3-5-sonnet-latest
# offline path:
python -m eval.llm_advise.judge \
--in eval/llm_advise/results-mock.json \
--out eval/llm_advise/results-mock.judged.json \
--judge mock:strict
Judge output is a strict JSON: accuracy, defensiveness, specificity
(1-5 each), and an explicit leak flag. We aggregate per-model into the
leaderboard.
Roadmap
- More scanners (Dockerfile hardening, IaC misconfig, browser extension manifests, mobile app permissions).
- Differential mode: compare two indexes and surface only newly-introduced findings (CI gate).
- Signed releases (sigstore / cosign).
- Web UI on top of the shared index.
License
MIT.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aegis_sec-0.1.0.tar.gz.
File metadata
- Download URL: aegis_sec-0.1.0.tar.gz
- Upload date:
- Size: 38.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdd8cec8c8180147d7545e92a7cdc443427824998ed94e18efd50bc9246ce59a
|
|
| MD5 |
22871b7d16c2beda2151f85074ce8495
|
|
| BLAKE2b-256 |
d1e3082d79d8f417809b7993c212195d74a11360e52b883ae922d71ca79de955
|
Provenance
The following attestation bundles were made for aegis_sec-0.1.0.tar.gz:
Publisher:
release.yml on verrysimatupang99/aegis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aegis_sec-0.1.0.tar.gz -
Subject digest:
bdd8cec8c8180147d7545e92a7cdc443427824998ed94e18efd50bc9246ce59a - Sigstore transparency entry: 1614801818
- Sigstore integration time:
-
Permalink:
verrysimatupang99/aegis@d2706a46f9cbdc20d53f0107b3d494b974da3c94 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/verrysimatupang99
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d2706a46f9cbdc20d53f0107b3d494b974da3c94 -
Trigger Event:
push
-
Statement type:
File details
Details for the file aegis_sec-0.1.0-py3-none-any.whl.
File metadata
- Download URL: aegis_sec-0.1.0-py3-none-any.whl
- Upload date:
- Size: 38.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03794389fab4c8cc3004b4f58c74e6275ca732d507ab3c499a65a3cda7d7df89
|
|
| MD5 |
dbc087c22a73dfe784df0f09584c877d
|
|
| BLAKE2b-256 |
bd11c6222802d7fd62381d12ad6ec82707ec9762ef1596f37201cc4c915f8342
|
Provenance
The following attestation bundles were made for aegis_sec-0.1.0-py3-none-any.whl:
Publisher:
release.yml on verrysimatupang99/aegis
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aegis_sec-0.1.0-py3-none-any.whl -
Subject digest:
03794389fab4c8cc3004b4f58c74e6275ca732d507ab3c499a65a3cda7d7df89 - Sigstore transparency entry: 1614801832
- Sigstore integration time:
-
Permalink:
verrysimatupang99/aegis@d2706a46f9cbdc20d53f0107b3d494b974da3c94 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/verrysimatupang99
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d2706a46f9cbdc20d53f0107b3d494b974da3c94 -
Trigger Event:
push
-
Statement type: