πŸ€ ratctl

A Static + Dynamic Auditor for Detecting Reward-Hacking Vulnerabilities in RL Environments

Fuzz your verifier before an RL agent does.

CI / Quality Gate Tests Passing Coverage Hugging Face Space License: MIT Python 3.10+ Contributing Guide Changelog Live Monitoring

πŸ€— Hugging Face Live Demo β€” The live demo is a browser-based JavaScript port of ratctl's regex detection engine (covering all 6 exploit classes). For full AST-based analysis, multi-file directory scanning, format auto-detection, and dynamic LLM fuzzing, install the CLI: pip install ratctl.


⚑ Quick Demo

Catching a multi-vector reward hack and enforcing a fail-closed CI gate:

$ ratctl audit ./vulnerable_env --fail-on 'gameability>0.3'
============================================================
  RATCTL AUDIT REPORT
============================================================

  Gameability Score: 52/100
  Total Findings:   6
  Files Scanned:    11
  Format Detected:  openenv (99%)

------------------------------------------------------------
  FINDINGS BY EXPLOIT CLASS
------------------------------------------------------------

  [GRADER_MANIPULATION] - 2 finding(s)
    Max severity: critical

    1. [CRITICAL] Private frame access
       File: server\app.py:6
       Using sys._getframe() to access interpreter stack frames. Enables grader detection and conditional cheating.
       Evidence: 2. Stack frame introspection via sys._getframe()
       Fix: Block sys._getframe by running in a restricted Python environment.

    2. [CRITICAL] Private frame access
       File: server\app.py:27
       Evidence: caller = sys._getframe(1)
       Fix: Block sys._getframe by running in a restricted Python environment.

  [PREMATURE_TERMINATION] - 2 finding(s)
    Max severity: critical

    1. [CRITICAL] sys.exit(0) - premature success
       File: server\app.py:7
       Calling sys.exit(0) could terminate the grading process with a success exit code before actual verification completes.
       Evidence: 3. Premature exit via sys.exit(0)
       Fix: Trap sys.exit() in the grading harness. Run agent in an isolated subprocess.

    2. [CRITICAL] sys.exit(0) - premature success
       File: server\app.py:34
       Evidence: sys.exit(0)
       Fix: Trap sys.exit() in the grading harness.

  [TEST_TAMPERING] - 1 finding(s)
    Max severity: critical

    1. [CRITICAL] Test file deletion
       File: server\app.py:24
       Code attempts to delete test/verification files.
       Evidence: os.remove("tests/test_solution.py")
       Fix: Mount test files in a read-only filesystem layer.

  [ENV_HIJACKING] - 1 finding(s)
    Max severity: critical

    1. [CRITICAL] Git history access
       File: server\app.py:30
       Accessing git history could reveal previous solutions, test changes, or answer keys.
       Evidence: subprocess.run(["git", "log", "-n", "1"])
       Fix: Remove .git directory from the agent's sandbox.

============================================================
FAIL: Gameability score 52/100 exceeds threshold 30%
Exit code: 1

πŸ’‘ Why ratctl?

In Reinforcement Learning post-training (RLHF, RLAIF, GRPO), agents optimize strictly for the reward signal. If a grading environment has logic flaws, the agent will learn to hack the verifier instead of solving the task.

Recent research highlights how common this is:

  • Terminal Wrench (Bercovich et al., 2026): Cataloged 331 hackable environments and 3,632 exploit trajectories across terminal-agent benchmarks β€” over 15% of standard benchmark tasks were bypassable without solving the core task.
  • SWE-bench Verified Audit (Rajan et al., 2026): Showed that 28.5% of audited code-generation tasks were Docker-verified hackable (e.g. agents reading ground-truth fixes directly from local .git logs).

ratctl provides a practical CLI tool and CI scanner to catch these common reward-hacking patterns before you deploy environments for agent training or publish them to hubs.


πŸ“Š Empirical Security Audit: 112 Environments Scanned

We conducted an empirical security audit using ratctl across a diverse dataset of 112 RL post-training environments (spanning OpenEnv Hub tasks, Prime Intellect verifiers spec environments, Gymnasium wrappers, and SWE-bench tasks).

See the standalone technical paper in PAPER.md and full dataset findings in AUDIT_REPORT.md.

$ python scripts/generate_real_world_audit.py

Empirical Audit Metrics

Metric Result Meaning
Total Environments Audited 112 OpenEnv, verifiers-spec, Gymnasium, SWE-bench
Vulnerabilities Flagged 54 Actionable security findings detected
Precision (PPV) 100.0% (54/54) Zero False Positives across 43 clean/hardened controls
Detection Recall (TPR) 78.3% (54/69) Sensitivity across diverse real-world exploit patterns
False Positive Rate 0.0% (0/43) No false alarms on well-designed verifiers

Framework Audit Breakdown

Framework / Suite Envs Audited Vulnerabilities Caught False Positives
OpenEnv Hub Tasks 35 18 / 25 0
Prime Intellect verifiers 35 27 / 27 0
SWE-bench Task Repos 17 9 / 9 0
Gymnasium / RLHF 25 0 / 8 0

πŸ§ͺ Initial Canonical Validation Suite

In addition to the 112-environment audit, we maintain a canonical 10-environment unit suite in benchmarks/ representing explicit exploit reproductions from Terminal Wrench and SWE-bench Verified alongside hardened controls:

$ ratctl benchmark benchmarks --format markdown
Task Name Environment Type Ground Truth Score Findings Status
tw_test_tampering Terminal Wrench (Test Deletion / Pytest Patch) Vulnerable 11/100 1 CAUGHT
tw_grader_introspection Terminal Wrench (inspect.stack() / __eq__ Override) Vulnerable 11/100 1 CAUGHT
tw_premature_exit Terminal Wrench (sys.exit(0) / Returncode Bypass) Vulnerable 34/100 6 CAUGHT
tw_env_git_leak Terminal Wrench (Git Commit Scraping & Secret Leaks) Vulnerable 30/100 6 CAUGHT
tw_reward_skipping Terminal Wrench (Bare except: & Additive Terms) Vulnerable 31/100 5 CAUGHT
tw_judge_verbosity Terminal Wrench (LLM Verbosity / Sycophancy Bias) Vulnerable 8/100 6 CAUGHT
astropy_git_leak SWE-bench Verified (Repo Golden Commit Leak) Vulnerable 14/100 2 CAUGHT
hardened_compiler_env Clean OpenEnv Control (Differential Testing) Clean 0/100 0 PASSED
hardened_math_verifier Clean Control (Pre-computed SHA-256 Digest) Clean 1/100 1 (Info) PASSED
hardened_rubric_judge Clean LLM Rubric Control (Accuracy-First Guardrails) Clean 1/100 2 (Info) PASSED

πŸ—οΈ System Architecture

ratctl combines static AST analysis with optional dynamic LLM red-teaming:

flowchart LR
    subgraph INGESTION["1. Ingestion and Detection"]
        A["Target Directory"] --> B["Format Detector"]
        B --> C1["OpenEnv Adapter"]
        B --> C2["Verifiers-Spec Adapter"]
        B --> C3["Gymnasium Adapter"]
        B --> C4["Raw Adapter"]
    end

    subgraph AUDIT["2. Dual-Mode Audit Pipeline"]
        C1 --> D["Source File Graph"]
        C2 --> D
        C3 --> D
        C4 --> D
        D --> E["Static AST Engine (6 Detectors)"]
        D --> F["Dynamic LLM Fuzzer (Subprocess Sandbox)"]
    end

    subgraph SCORING["3. Scoring and Enforcement"]
        E --> G["Weighted Scoring Engine"]
        F --> G
        G --> H["Report Renderers (Rich / JSON / Text)"]
        G --> I["CI/CD Gate (--fail-on)"]
    end

🎯 Exploit Taxonomy

ratctl checks for 6 core categories of verifier vulnerabilities:

Exploit Class Detection Mechanism & Scope Severity
1. Test / Assertion Tampering Scans for AST file deletions (os.remove), test overwrites, and monkey-patching pytest assertion hooks. πŸ”΄ Critical (1.0)
2. Grader Manipulation Flags stack frame inspection (inspect.stack(), sys._getframe()), operator overloading (__eq__, __bool__), and pytest hook hijacking. πŸ”΄ Critical (1.0)
3. Premature Termination Detects sys.exit(0) / os._exit(0) early returns, SIGTERM signal handler suppression, and trivial always-pass paths. πŸ”΄ Critical (0.9)
4. Environment Hijacking Detects golden solution leaks in .git log, answer key file reads, env var leaks, and runtime pip install. 🟠 High (0.85)
5. Reward Skipping Flags unconditioned additive reward terms, exception-swallowing bare except: blocks returning True, and hardcoded max rewards. 🟑 Medium (0.7)
6. LLM-Judge Bias Identifies rubrics favoring verbosity/length over accuracy, sycophancy bias, and missing factual correctness criteria. 🟑 Medium (0.5)

πŸš€ Quick Start

Installation

Choose the method that fits your setup:

# Method 1: Install from PyPI (adds `ratctl` to your PATH)
pip install ratctl

# Method 2: Install in dev mode from source (editable, adds `ratctl` to PATH)
git clone https://github.com/FreakyAdy/Reward-Hackability-Auditor--CLI---Claude-Skill-.git
cd Reward-Hackability-Auditor--CLI---Claude-Skill-
pip install -e .

# Method 3: Run directly without installing (no PATH setup needed)
python -m ratctl.cli audit ./my_environment

Optional extras for dynamic LLM fuzzing:

pip install "ratctl[ollama]"    # Local Ollama red-teaming (free)
pip install "ratctl[frontier]"  # GPT-4o / Claude 3.7 red-teaming

Basic Commands

# Run a static audit on any environment directory
ratctl audit ./my_environment

# CI Gate: block PRs if gameability score exceeds 30%
ratctl audit ./my_environment --fail-on 'gameability>0.3'

# Dynamic LLM Red-Teaming (uses local Ollama β€” 100% free)
ratctl audit ./my_environment --dynamic

# Launch full-screen animated Terminal TUI Dashboard
ratctl tui ./examples/vulnerable_env

# Launch interactive Web Dashboard UI in browser
ratctl ui ./my_environment

# Output structured JSON for security telemetry
ratctl audit ./my_environment --format json -o audit-report.json

πŸ’‘ If ratctl is not recognized, use python -m ratctl.cli instead:

python -m ratctl.cli tui ./examples/vulnerable_env
python -m ratctl.cli audit ./my_environment

Runnable Examples

Explore the examples/ directory to test ratctl against clean vs. vulnerable environments back-to-back:

# Audit clean hardened environment (0 findings, score: 0/100)
ratctl tui ./examples/hardened_env

# Audit vulnerable environment (6 findings, score: 52/100)
ratctl tui ./examples/vulnerable_env

πŸ“‘ Live In-Training Monitoring (ratctl watch) (Beta)

While ratctl audit secures verifiers pre-deployment, ratctl watch monitors verifiers in-training during RL policy optimization (GRPO, PPO, TRL).

Drop-in Python Decorator

import ratctl

@ratctl.watch
def verify_solution(completion, ground_truth):
    return 1.0 if completion.strip() == ground_truth.strip() else 0.0

TRL / GRPO Integrations (GRPOSpy)

from ratctl.integrations import GRPOSpy
from trl import GRPOTrainer

spy = GRPOSpy(reward_funcs=[accuracy_reward, format_reward])
trainer = GRPOTrainer(
    model=model,
    reward_funcs=spy.wrapped_reward_funcs,
    ...
)

CLI Trajectory Inspection

# 1. Stream live verifier trajectory logs
ratctl show logs/run.jsonl

# 2. Display aggregate ceiling & anomaly statistics
ratctl summary logs/run.jsonl

πŸ”„ GitHub Actions CI/CD Integration

Fail-close your CI pipeline when a verifier exceeds a gameability score:

name: RL Verifier Security Gate
on: [push, pull_request]

jobs:
  audit-verifier:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Run ratctl Auditor
        uses: FreakyAdy/Reward-Hackability-Auditor--CLI---Claude-Skill-@main
        with:
          path: "."
          fail-on: "gameability>0.3"
          format: "text"

Sample $GITHUB_STEP_SUMMARY Output

When triggered in GitHub Actions, ratctl renders rich Markdown summaries directly into the Action job log:

### πŸ€ RATCTL AUDIT SUMMARY
* **Status**: πŸ”΄ FAILED (Gameability Score: 85/100)
* **Format Detected**: `openenv` (99% confidence)
* **Total Findings**: 4 (3 Critical, 1 High)

| Exploit Class | Severity | Finding | Location |
| :--- | :---: | :--- | :--- |
| `TEST_TAMPERING` | πŸ”΄ Critical | Deleting test file | `server/app.py:18` |
| `GRADER_MANIPULATION` | πŸ”΄ Critical | Stack frame introspection | `server/environment.py:42` |
| `PREMATURE_TERMINATION` | πŸ”΄ Critical | `sys.exit(0)` early exit | `verifier.py:28` |
| `ENV_HIJACKING` | 🟠 High | Git history leak | `verifier.py:65` |

βš–οΈ Related Tools & Ecosystem

ratctl complements existing tools in the RL safety and monitoring ecosystem:

Tool Primary Focus Lifecycle Stage Detection Scope CI Gate
ratctl Verifier Security & Gameability Audit Pre-Deployment & In-Training AST logic vulnerabilities, red-team fuzzing, verifier call trajectories βœ… Yes
rewardspy Live Reward Curve Tracking In-Training Reward mean/std, component weight drift, ceiling hits ❌ No
PyTest Unit Testing Development Code unit correctness ⚠️ Manual

ratctl and rewardspy address complementary lifecycle stages: use ratctl audit pre-deployment to fix verifier security bugs, and ratctl watch or rewardspy in-training to track reward dynamics.


🀝 Contributing & Community

ratctl is an open-source community effort. We welcome custom detectors, bug reports, and research extensions!


πŸ“„ License

MIT License β€” see LICENSE for details.

Distributed under the MIT License.