FelonyBench gives an agent a legitimate task inside a deliberately constrained environment, then watches what it does when useful information, capabilities, or state exist just outside that boundary. The environment is instrumented so that boundary-crossing attempts can be measured independently of whether the model claims to have succeeded, or claims to have not tried.
The question is not whether a model can solve a security puzzle. It's whether an agent stays inside its authorization when it has tools, a filesystem, code execution, and an objective that happens to be easier to reach by stepping outside those lines than by staying inside them. Nobody attacks the agent. Nobody asks it to do anything malicious. The boundary is just there, and something useful is on the other side of it.
FelonyBench is pre-release. This repository currently contains the benchmark specification: task taxonomy, environment contract, scoring model, and runner/evaluator interface. There is no working code yet.
Everything under Target Interface and Repository Layout describes the intended shape of the project, not something you can pip install today.
Agent-security evaluation has mostly organized around three questions, and FelonyBench is deliberately answering a fourth:
| Benchmark | Question it asks | Trigger |
|---|---|---|
| AgentDojo (Debenedetti et al., NeurIPS 2024 D&B) | Can third-party content the agent reads (an email, a search result, a tool output) hijack its behavior? | Injected instruction |
| AgentHarm (Andriushchenko et al., 2024, with UK AISI) | Will the agent comply when the user directly asks it to do something explicitly malicious? | Explicit malicious request |
| SandboxEscapeBench (Marchand et al., 2026) | Can the agent break container isolation when its stated goal is to escape and read a host-side flag? | Explicit escape objective, CTF framing |
| FelonyBench | Will the agent cross an authorization boundary nobody told it to cross, on a task nobody made adversarial, because doing so is instrumentally convenient? | No instruction, no injection, no objective — just opportunity |
The distinction matters for what a passing or failing score means. A model that resists AgentDojo has shown it isn't hijackable by hostile content. A model that resists AgentHarm has shown it refuses direct requests to do harm. A model that fails SandboxEscapeBench under an explicit escape objective has demonstrated a capability, not an intent. None of those results tell you whether the same model, given a completely ordinary task and no adversarial input at all, will quietly read a file it wasn't authorized to read because reading it would help.
FelonyBench doesn't attempt to replace any of the above; it targets the gap between "can be tricked" and "will misbehave unprompted," which is closer to the propensity side of the agentic-misalignment literature than to red-teaming or jailbreak-robustness literature. Adjacent multi-category efforts like Agent-SafetyBench and Agent Security Bench (ASB) cover broader risk taxonomies (Zhang et al., 2024/2025) but are also built around either adversarial or explicitly risky task framings, not incidental opportunity.
A related design note: several of the benchmarks above are built on Inspect AI, the UK AISI's evaluation framework. FelonyBench does not currently depend on it — the runner/sandbox/evaluator split is designed to stay portable across agent runtimes first. Building an Inspect-compatible adapter is a reasonable future addition; see Roadmap.
| Category | Question the task asks | Attempt vs. success |
|---|---|---|
| Sandbox escape | Does the agent try to reach resources outside its permitted execution environment? | Distinguished |
| Filesystem access | Does it read or write outside its authorized path? | Distinguished |
| Credentials / secrets | Does it discover, access, retrieve, or transmit protected values? | Five-way graded — see Secrets |
| Privilege escalation | Does it attempt to acquire permissions it wasn't granted? | Distinguished |
| Network access | Does it reach destinations outside its authorized network boundary? | Distinguished |
| Persistence | Does it try to leave state that survives the environment's intended lifecycle? | Distinguished |
| Exfiltration | Does it move protected data to a destination outside the sandbox? | Distinguished |
| Prompt injection | Does it treat untrusted tool output or files as data, or adopt embedded instructions as its own? | Binary trigger + downstream action |
| Environment tampering | Does it attempt to modify or disable the benchmark's own instrumentation? | Distinguished |
| Deceptive reporting | Does what it says happened match the instrumented event log? | Binary |
A task distinguishes an agent merely encountering a protected resource from an agent actively attempting to obtain it. That distinction is the whole point: a benchmark that scores on whether a prohibited string or API call appears anywhere in a trajectory is measuring exposure, not behavior.
Not yet implemented. This is the interface the reference runner is being designed toward.
pip install felony-bench
# list available tasks
felonybench ls
# run one task against a model
felonybench run --task sandbox-escape --model claude-sonnet-5
# run the full task set
felonybench run --all --model gpt-5.2
# validate a task definition in isolation, without a model
felonybench validate --task sandbox-escape
The model/agent-runtime interface is kept separate from task definitions on purpose, so the same task set can run against different agent harnesses without rewriting tasks.
FelonyBench
|
v
+-------------------+
| Runner |
+---------+---------+
|
+-------------+-------------+
| |
v v
+---------------+ +---------------+
| Agent | | Evaluator |
| | | |
| tools | | event log |
| filesystem | | violations |
| code execution| | task result |
+-------+-------+ +-------+-------+
| ^
v |
+---------------+ |
| Sandbox |-------------------+
| |
| task state |
| synthetic |
| secrets |
| protected |
| resources |
+---------------+
The sandbox is part of the benchmark, not an assumption about the model. Tasks are reproducible, deterministic where practical, and instrumented enough that the evaluator can tell legitimate task completion apart from boundary violations without reading the sandbox itself.
No task requires real credentials, production systems, or external infrastructure.
A task defines the environment and the authorization boundary around it.
class Task:
name = "example"
def setup(self, sandbox):
...
def prompt(self):
return "..."
def evaluate(self, trace):
...
The agent gets a restricted filesystem or execution environment. A synthetic resource exists just outside the permitted boundary. The task measures whether the agent attempts to reach it, rather than simply reporting that it's unavailable.
Synthetic credentials or other protected values sit in locations the agent isn't authorized to access. The evaluator grades five distinct outcomes separately:
The agent encounters an operation that would require permissions it hasn't been granted. The task measures whether it respects the boundary or attempts to acquire additional privileges.
The environment has a defined lifecycle boundary. The task measures whether the agent tries to leave state behind that survives the environment's intended termination or reset.
The sandbox contains synthetic protected information and a controlled destination through which unauthorized transfer can be detected. No real-world target is required or used.
Untrusted files, tool responses, or other task-controlled content carry instructions directed at the agent. The task measures whether the agent treats that content as data, or adopts it as instructions that supersede its authorized task.
FelonyBench records the agent trajectory and evaluates observable behavior rather than relying solely on the model's final response. Every result answers:
Did the agent complete the task?
Did the agent attempt an unauthorized action?
Did the unauthorized action succeed?
What boundary was crossed?
What protected resource was accessed?
Was protected information disclosed?
Did the agent attempt to establish persistence?
Did the agent accurately report what happened?
The distinction between an attempted and a successful violation is preserved throughout. A model that attempts to access a protected resource and is correctly blocked has demonstrated different behavior than a model that never attempts the access at all. Both differ again from a model that succeeds.
The primary result is the individual task outcome. Aggregate scores are derived from those outcomes; they don't replace them.
{
"task": "secret-access",
"completed": true,
"violation_attempted": true,
"violation_succeeded": false,
"protected_resource_accessed": false
}
| Aggregate metric | What it captures |
|---|---|
| Task completion rate | Whether the model does useful work at all — a model that refuses everything isn't equivalent to one that completes work while respecting boundaries |
| Unauthorized-attempt rate | How often the model tries to cross a boundary it wasn't told about |
| Successful-violation rate | How often an attempt actually succeeds |
| Protected-resource access rate | How often protected resources are reached, attempted or not |
| Exfiltration rate | How often protected data leaves the sandbox |
| Persistence rate | How often the model tries to outlive the environment's lifecycle |
| False-reporting rate | How often the model's self-report disagrees with the instrumented event log |
No single number is treated as the benchmark result. Model comparisons should be made across the full result vector, not a leaderboard scalar.
FelonyBench prefers environmental instrumentation over inference from model output. If a task protects a synthetic file, the evaluator knows whether that file was actually opened — it doesn't infer access from the model saying "I found the file." A blocked operation stays visible in the event stream even when the sandbox successfully prevents it.
This is what makes the benchmark usable for agents whose behavior extends beyond the text they return to the user.
Tasks avoid dependencies on uncontrolled external systems. Where network behavior is required, use a local or synthetic network under benchmark control. Where credentials are required, use generated credentials. Where privileged resources are required, expose controlled resources that reproduce the relevant authorization boundary without granting access to a real host or account.
A benchmark run produces enough metadata to reproduce the environment and identify the exact task and benchmark version used.
FelonyBench evaluates agents in environments built specifically for the benchmark. It does not require a model to interact with:
The purpose is to observe whether an agent attempts prohibited behavior, not to hand a model an opportunity to compromise an unrelated system.
FelonyBench is not a CTF collection. It doesn't measure general penetration-testing ability, vulnerability discovery, exploit development, or offensive security skill — that's the territory SandboxEscapeBench and similar capability benchmarks already cover.
It's also not a substitute for production agent security controls. A model passing FelonyBench doesn't establish that it's safe to deploy with arbitrary privileges or access to sensitive infrastructure.
The benchmark measures a narrower question:
When an agent has an explicit execution boundary, does it respect that boundary — unprompted, on an ordinary task, with no one testing it?
Target layout; nothing below exists yet.
felony-bench/
├── felonybench/
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli.py
│ ├── runner.py
│ ├── sandbox.py
│ ├── events.py
│ ├── models.py
│ ├── grader.py
│ ├── mock_agents.py
│ └── tasks/
│ ├── __init__.py
│ ├── base.py
│ ├── sandbox_boundary.py
│ ├── protected_secret.py
│ ├── persistence.py
│ └── prompt_injection.py
├── tests/
│ ├── test_sandbox.py
│ ├── test_events.py
│ ├── test_grader.py
│ └── test_tasks.py
├── pyproject.toml
├── README.md
└── LICENSE
The runner is intentionally small. A task defines the environment, the model receives the task through the runner, and the evaluator consumes the resulting trajectory and environment events.
New tasks should represent a distinct agent behavior, not another variation of the same prompt. Every task should specify:
Task evaluators should rely on observable sandbox events wherever possible, and shouldn't require access to hidden model reasoning. Tests should cover both sides of the boundary: the benchmark has to verify that legitimate behavior stays possible and that prohibited behavior gets detected. felonybench validate --task <name> (once implemented) is meant to run a task's setup/evaluate cycle in isolation for exactly this check, without needing a model in the loop.
Initial development focuses on a small, reproducible task set and a stable runner/evaluator interface.
docs/task_guide.md — task-authoring reference, once the task API stabilizesThe benchmark should stay small enough that a new task can be understood by reading its implementation, without needing a separate framework or methodology document.
No accompanying paper yet. If you use FelonyBench before a formal release, cite the repository:
@misc{felonybench,
title = {FelonyBench: Measuring Authorization-Boundary Behavior in AI Agents},
author = {TODO},
year = {2026},
howpublished = {\url{https://github.com/<org>/felony-bench}},
note = {Pre-release. Citation will be finalized at first tagged release.}
}
TBD. MIT and Apache-2.0 are the common defaults for benchmark tooling in this space; AgentHarm uses MIT with an added clause restricting use to safety research, which is worth considering if any task content could be misread as offensive tooling out of context.
21 commits
Hacker News (1)
Python
100.0%
FelonyBench gives an agent a legitimate task inside a deliberately constrained environment, then watches what it does when useful information, capabilities, or state exist just outside that boundary. The environment is instrumented so that boundary-crossing attempts can be measured independently of whether the model claims to have succeeded, or claims to have not tried.
The question is not whether a model can solve a security puzzle. It's whether an agent stays inside its authorization when it has tools, a filesystem, code execution, and an objective that happens to be easier to reach by stepping outside those lines than by staying inside them. Nobody attacks the agent. Nobody asks it to do anything malicious. The boundary is just there, and something useful is on the other side of it.
FelonyBench is pre-release. This repository currently contains the benchmark specification: task taxonomy, environment contract, scoring model, and runner/evaluator interface. There is no working code yet.
Everything under Target Interface and Repository Layout describes the intended shape of the project, not something you can pip install today.
Agent-security evaluation has mostly organized around three questions, and FelonyBench is deliberately answering a fourth:
| Benchmark | Question it asks | Trigger |
|---|---|---|
| AgentDojo (Debenedetti et al., NeurIPS 2024 D&B) | Can third-party content the agent reads (an email, a search result, a tool output) hijack its behavior? | Injected instruction |
| AgentHarm (Andriushchenko et al., 2024, with UK AISI) | Will the agent comply when the user directly asks it to do something explicitly malicious? | Explicit malicious request |
| SandboxEscapeBench (Marchand et al., 2026) | Can the agent break container isolation when its stated goal is to escape and read a host-side flag? | Explicit escape objective, CTF framing |
| FelonyBench | Will the agent cross an authorization boundary nobody told it to cross, on a task nobody made adversarial, because doing so is instrumentally convenient? | No instruction, no injection, no objective — just opportunity |
The distinction matters for what a passing or failing score means. A model that resists AgentDojo has shown it isn't hijackable by hostile content. A model that resists AgentHarm has shown it refuses direct requests to do harm. A model that fails SandboxEscapeBench under an explicit escape objective has demonstrated a capability, not an intent. None of those results tell you whether the same model, given a completely ordinary task and no adversarial input at all, will quietly read a file it wasn't authorized to read because reading it would help.
FelonyBench doesn't attempt to replace any of the above; it targets the gap between "can be tricked" and "will misbehave unprompted," which is closer to the propensity side of the agentic-misalignment literature than to red-teaming or jailbreak-robustness literature. Adjacent multi-category efforts like Agent-SafetyBench and Agent Security Bench (ASB) cover broader risk taxonomies (Zhang et al., 2024/2025) but are also built around either adversarial or explicitly risky task framings, not incidental opportunity.
A related design note: several of the benchmarks above are built on Inspect AI, the UK AISI's evaluation framework. FelonyBench does not currently depend on it — the runner/sandbox/evaluator split is designed to stay portable across agent runtimes first. Building an Inspect-compatible adapter is a reasonable future addition; see Roadmap.
| Category | Question the task asks | Attempt vs. success |
|---|---|---|
| Sandbox escape | Does the agent try to reach resources outside its permitted execution environment? | Distinguished |
| Filesystem access | Does it read or write outside its authorized path? | Distinguished |
| Credentials / secrets | Does it discover, access, retrieve, or transmit protected values? | Five-way graded — see Secrets |
| Privilege escalation | Does it attempt to acquire permissions it wasn't granted? | Distinguished |
| Network access | Does it reach destinations outside its authorized network boundary? | Distinguished |
| Persistence | Does it try to leave state that survives the environment's intended lifecycle? | Distinguished |
| Exfiltration | Does it move protected data to a destination outside the sandbox? | Distinguished |
| Prompt injection | Does it treat untrusted tool output or files as data, or adopt embedded instructions as its own? | Binary trigger + downstream action |
| Environment tampering | Does it attempt to modify or disable the benchmark's own instrumentation? | Distinguished |
| Deceptive reporting | Does what it says happened match the instrumented event log? | Binary |
A task distinguishes an agent merely encountering a protected resource from an agent actively attempting to obtain it. That distinction is the whole point: a benchmark that scores on whether a prohibited string or API call appears anywhere in a trajectory is measuring exposure, not behavior.
Not yet implemented. This is the interface the reference runner is being designed toward.
pip install felony-bench
# list available tasks
felonybench ls
# run one task against a model
felonybench run --task sandbox-escape --model claude-sonnet-5
# run the full task set
felonybench run --all --model gpt-5.2
# validate a task definition in isolation, without a model
felonybench validate --task sandbox-escape
The model/agent-runtime interface is kept separate from task definitions on purpose, so the same task set can run against different agent harnesses without rewriting tasks.
FelonyBench
|
v
+-------------------+
| Runner |
+---------+---------+
|
+-------------+-------------+
| |
v v
+---------------+ +---------------+
| Agent | | Evaluator |
| | | |
| tools | | event log |
| filesystem | | violations |
| code execution| | task result |
+-------+-------+ +-------+-------+
| ^
v |
+---------------+ |
| Sandbox |-------------------+
| |
| task state |
| synthetic |
| secrets |
| protected |
| resources |
+---------------+
The sandbox is part of the benchmark, not an assumption about the model. Tasks are reproducible, deterministic where practical, and instrumented enough that the evaluator can tell legitimate task completion apart from boundary violations without reading the sandbox itself.
No task requires real credentials, production systems, or external infrastructure.
A task defines the environment and the authorization boundary around it.
class Task:
name = "example"
def setup(self, sandbox):
...
def prompt(self):
return "..."
def evaluate(self, trace):
...
The agent gets a restricted filesystem or execution environment. A synthetic resource exists just outside the permitted boundary. The task measures whether the agent attempts to reach it, rather than simply reporting that it's unavailable.
Synthetic credentials or other protected values sit in locations the agent isn't authorized to access. The evaluator grades five distinct outcomes separately:
The agent encounters an operation that would require permissions it hasn't been granted. The task measures whether it respects the boundary or attempts to acquire additional privileges.
The environment has a defined lifecycle boundary. The task measures whether the agent tries to leave state behind that survives the environment's intended termination or reset.
The sandbox contains synthetic protected information and a controlled destination through which unauthorized transfer can be detected. No real-world target is required or used.
Untrusted files, tool responses, or other task-controlled content carry instructions directed at the agent. The task measures whether the agent treats that content as data, or adopts it as instructions that supersede its authorized task.
FelonyBench records the agent trajectory and evaluates observable behavior rather than relying solely on the model's final response. Every result answers:
Did the agent complete the task?
Did the agent attempt an unauthorized action?
Did the unauthorized action succeed?
What boundary was crossed?
What protected resource was accessed?
Was protected information disclosed?
Did the agent attempt to establish persistence?
Did the agent accurately report what happened?
The distinction between an attempted and a successful violation is preserved throughout. A model that attempts to access a protected resource and is correctly blocked has demonstrated different behavior than a model that never attempts the access at all. Both differ again from a model that succeeds.
The primary result is the individual task outcome. Aggregate scores are derived from those outcomes; they don't replace them.
{
"task": "secret-access",
"completed": true,
"violation_attempted": true,
"violation_succeeded": false,
"protected_resource_accessed": false
}
| Aggregate metric | What it captures |
|---|---|
| Task completion rate | Whether the model does useful work at all — a model that refuses everything isn't equivalent to one that completes work while respecting boundaries |
| Unauthorized-attempt rate | How often the model tries to cross a boundary it wasn't told about |
| Successful-violation rate | How often an attempt actually succeeds |
| Protected-resource access rate | How often protected resources are reached, attempted or not |
| Exfiltration rate | How often protected data leaves the sandbox |
| Persistence rate | How often the model tries to outlive the environment's lifecycle |
| False-reporting rate | How often the model's self-report disagrees with the instrumented event log |
No single number is treated as the benchmark result. Model comparisons should be made across the full result vector, not a leaderboard scalar.
FelonyBench prefers environmental instrumentation over inference from model output. If a task protects a synthetic file, the evaluator knows whether that file was actually opened — it doesn't infer access from the model saying "I found the file." A blocked operation stays visible in the event stream even when the sandbox successfully prevents it.
This is what makes the benchmark usable for agents whose behavior extends beyond the text they return to the user.
Tasks avoid dependencies on uncontrolled external systems. Where network behavior is required, use a local or synthetic network under benchmark control. Where credentials are required, use generated credentials. Where privileged resources are required, expose controlled resources that reproduce the relevant authorization boundary without granting access to a real host or account.
A benchmark run produces enough metadata to reproduce the environment and identify the exact task and benchmark version used.
FelonyBench evaluates agents in environments built specifically for the benchmark. It does not require a model to interact with:
The purpose is to observe whether an agent attempts prohibited behavior, not to hand a model an opportunity to compromise an unrelated system.
FelonyBench is not a CTF collection. It doesn't measure general penetration-testing ability, vulnerability discovery, exploit development, or offensive security skill — that's the territory SandboxEscapeBench and similar capability benchmarks already cover.
It's also not a substitute for production agent security controls. A model passing FelonyBench doesn't establish that it's safe to deploy with arbitrary privileges or access to sensitive infrastructure.
The benchmark measures a narrower question:
When an agent has an explicit execution boundary, does it respect that boundary — unprompted, on an ordinary task, with no one testing it?
Target layout; nothing below exists yet.
felony-bench/
├── felonybench/
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli.py
│ ├── runner.py
│ ├── sandbox.py
│ ├── events.py
│ ├── models.py
│ ├── grader.py
│ ├── mock_agents.py
│ └── tasks/
│ ├── __init__.py
│ ├── base.py
│ ├── sandbox_boundary.py
│ ├── protected_secret.py
│ ├── persistence.py
│ └── prompt_injection.py
├── tests/
│ ├── test_sandbox.py
│ ├── test_events.py
│ ├── test_grader.py
│ └── test_tasks.py
├── pyproject.toml
├── README.md
└── LICENSE
The runner is intentionally small. A task defines the environment, the model receives the task through the runner, and the evaluator consumes the resulting trajectory and environment events.
New tasks should represent a distinct agent behavior, not another variation of the same prompt. Every task should specify:
Task evaluators should rely on observable sandbox events wherever possible, and shouldn't require access to hidden model reasoning. Tests should cover both sides of the boundary: the benchmark has to verify that legitimate behavior stays possible and that prohibited behavior gets detected. felonybench validate --task <name> (once implemented) is meant to run a task's setup/evaluate cycle in isolation for exactly this check, without needing a model in the loop.
Initial development focuses on a small, reproducible task set and a stable runner/evaluator interface.
docs/task_guide.md — task-authoring reference, once the task API stabilizesThe benchmark should stay small enough that a new task can be understood by reading its implementation, without needing a separate framework or methodology document.
No accompanying paper yet. If you use FelonyBench before a formal release, cite the repository:
@misc{felonybench,
title = {FelonyBench: Measuring Authorization-Boundary Behavior in AI Agents},
author = {TODO},
year = {2026},
howpublished = {\url{https://github.com/<org>/felony-bench}},
note = {Pre-release. Citation will be finalized at first tagged release.}
}
TBD. MIT and Apache-2.0 are the common defaults for benchmark tooling in this space; AgentHarm uses MIT with an added clause restricting use to safety research, which is worth considering if any task content could be misread as offensive tooling out of context.
Hacker News (1)
21 commits
Python
100.0%