Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project are documented here. The format is based on
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.19.0]

### Added
- **AG040 — Model output executed as code or command (insecure output handling, OWASP LLM02).**
Flags the output of an LLM call (`invoke`/`predict`/`generate`/`complete`, or
`completions`/`messages`.`create`) flowing into a code or shell execution sink
(`eval`/`exec`/`compile`/`os.system`/`os.popen`/`subprocess.*`) — inline, via a
single-function variable, or through `.content` / `.choices[...].message.content`
accessors. This is the first rule to use the engine's source tracking to connect a
model-output *source* to a dangerous *sink*. MITRE ATT&CK T1059.

## [0.18.0]

### Added
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ destruction (`terminate_instances`, `delete_bucket`, `delete_cluster`, k8s teard
money movement without approval (`Refund`/`Payout`/`Transfer.create`), persistence/backdoor
writes (SSH `authorized_keys`, `crontab`, `sudoers`), runtime package installs (`pip install`),
IAM/privilege escalation (`create_access_key`, `attach_role_policy`), world-writable `chmod`,
insecure output handling (LLM output flowing into `eval`/`exec`/a shell),
known-vulnerable framework dependencies (version-validated CVEs), and more. Run
`autonomyproof rules list` for the full catalogue and `autonomyproof rules explain AG001`
for details. Every finding carries **OWASP Agentic, NIST AI RMF, ISO 42001, MITRE
Expand Down Expand Up @@ -142,7 +143,7 @@ re-run `autonomyproof baseline .` and commit the updated file in the same PR.
Use the action directly:

```yaml
- uses: autonomyproof/autonomyproof-cli@v0.18.0
- uses: autonomyproof/autonomyproof-cli@v0.19.0
with:
target: .
fail-on: high
Expand All @@ -169,7 +170,7 @@ Gate locally before a commit ever leaves your machine:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/autonomyproof/autonomyproof-cli
rev: v0.18.0
rev: v0.19.0
hooks:
- id: autonomyproof
```
Expand Down
5 changes: 3 additions & 2 deletions benchmark/CORPUS_RESULTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Labeled-corpus results (ground-truth precision & recall)

**Cases:** 150 · **Rules covered:** 33 · **Overall precision:** 1.000 · **Overall recall:** 1.000
**Cases:** 156 · **Rules covered:** 34 · **Overall precision:** 1.000 · **Overall recall:** 1.000

| Rule | pos | neg | TP | FP | FN | Precision | Recall | F1 |
|---|--:|--:|--:|--:|--:|--:|--:|--:|
Expand Down Expand Up @@ -37,8 +37,9 @@
| AG037 | 1 | 2 | 1 | 0 | 0 | 1.00 | 1.00 | 1.00 |
| AG038 | 2 | 2 | 2 | 0 | 0 | 1.00 | 1.00 | 1.00 |
| AG039 | 1 | 2 | 1 | 0 | 0 | 1.00 | 1.00 | 1.00 |
| AG040 | 3 | 3 | 3 | 0 | 0 | 1.00 | 1.00 | 1.00 |

**Totals:** TP 78 · FP 0 · FN 0 · TN 72
**Totals:** TP 81 · FP 0 · FN 0 · TN 75

Precision = of the cases where a rule fired, how many were true positives. Recall = of the cases where a rule should fire, how many did. Reproduce with `python benchmark/corpus_eval.py`.

8 changes: 8 additions & 0 deletions benchmark/corpus.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,14 @@ cases:
- {id: ag039-neg-safe, rule: AG039, label: negative, code: "import os\n@tool\ndef fix(p):\n os.chmod(p, 0o644)\n"}
- {id: ag039-neg-dynamic, rule: AG039, label: negative, code: "import os\n@tool\ndef fix(p, mode):\n os.chmod(p, mode)\n"}

# --- AG040 insecure model output executed as code/command ---
- {id: ag040-pos-eval, rule: AG040, label: positive, code: "def run(p):\n return eval(llm.invoke(p))\n"}
- {id: ag040-pos-var, rule: AG040, label: positive, code: "def run(p):\n code = llm.predict(p)\n exec(code)\n"}
- {id: ag040-pos-ossystem, rule: AG040, label: positive, code: "import os\ndef run(p):\n os.system(agent.generate(p))\n"}
- {id: ag040-neg-userinput, rule: AG040, label: negative, code: "def run(user_input):\n exec(user_input)\n"}
- {id: ag040-neg-nonmodel, rule: AG040, label: negative, code: "def run(u):\n data = requests.get(u).text\n exec(data)\n"}
- {id: ag040-neg-constant, rule: AG040, label: negative, code: "exec('print(1)')\n"}

# --- AG021 broadened deserialization sinks ---
- {id: ag021-pos-joblib, rule: AG021, label: positive, code: "import joblib\njoblib.load(f)\n"}
- {id: ag021-pos-pandas, rule: AG021, label: positive, code: "import pandas\npandas.read_pickle(f)\n"}
Expand Down
Loading
Loading