dexter-2k commited on
Commit
912b149
·
verified ·
1 Parent(s): c99b5c6

fix: mirror reference project structure - openenv section, POST /grader, openenv tag, HEALTHCHECK

Browse files
Files changed (4) hide show
  1. Dockerfile +19 -11
  2. README.md +10 -297
  3. openenv.yaml +99 -47
  4. server/environment.py +5 -1
Dockerfile CHANGED
@@ -1,27 +1,35 @@
1
  FROM python:3.11-slim
2
 
3
- ENV PYTHONDONTWRITEBYTECODE=1 \
4
- PYTHONUNBUFFERED=1 \
5
- PIP_NO_CACHE_DIR=1
6
-
7
  WORKDIR /app
8
 
 
9
  RUN apt-get update && apt-get install -y --no-install-recommends \
10
  bash \
11
  ca-certificates \
12
  curl \
 
13
  git \
14
  && rm -rf /var/lib/apt/lists/*
15
 
16
- COPY requirements.txt /app/requirements.txt
17
- RUN python -m pip install --upgrade pip && \
18
- python -m pip install -r /app/requirements.txt && \
19
- python -m pip install git-filter-repo
20
 
21
- COPY . /app
 
22
 
23
- RUN chmod +x /app/hf_space_entrypoint.sh
 
24
 
 
25
  EXPOSE 7860
26
 
27
- CMD ["bash", "/app/hf_space_entrypoint.sh"]
 
 
 
 
 
 
 
 
1
  FROM python:3.11-slim
2
 
 
 
 
 
3
  WORKDIR /app
4
 
5
+ # System dependencies
6
  RUN apt-get update && apt-get install -y --no-install-recommends \
7
  bash \
8
  ca-certificates \
9
  curl \
10
+ gcc \
11
  git \
12
  && rm -rf /var/lib/apt/lists/*
13
 
14
+ # Install Python dependencies
15
+ COPY requirements.txt .
16
+ RUN pip install --no-cache-dir -r requirements.txt && \
17
+ pip install --no-cache-dir git-filter-repo
18
 
19
+ # Copy application code
20
+ COPY . .
21
 
22
+ # Install the package itself
23
+ RUN pip install --no-cache-dir -e .
24
 
25
+ # HF Spaces default port
26
  EXPOSE 7860
27
 
28
+ # Health check
29
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=5 \
30
+ CMD curl -f http://localhost:7860/health || exit 1
31
+
32
+ ENV PYTHONUNBUFFERED=1
33
+ ENV PYTHONDONTWRITEBYTECODE=1
34
+
35
+ CMD ["uvicorn", "server.app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -4,304 +4,17 @@ emoji: 🔐
4
  colorFrom: indigo
5
  colorTo: red
6
  sdk: docker
7
- pinned: false
 
 
 
 
 
 
 
 
8
  ---
9
 
10
  # SecretsAuditEnv
11
 
12
- A reinforcement-learning benchmark that drops an AI agent into a git-backed codebase seeded with realistic secret leaks — hardcoded API keys, base64-encoded tokens, credentials buried in git history — and grades how quickly and safely the agent remediates every one. The environment runs as a stateless FastAPI server; the agent interacts over HTTP with bash commands and structured inspection actions, receiving a composite reward after every step that captures security progress, code health, and time efficiency.
13
-
14
- ## Why This Exists
15
-
16
- Production secret leaks remain a top-5 cause of cloud breaches. Developers commit API keys, push `.env` files, or leave credentials in migration scripts — then scramble to rotate and rewrite history. Existing linting tools flag secrets but don't fix them; LLM agents can, but there's no standardized benchmark to measure how well. **SecretsAuditEnv** fills that gap with a 13-task curriculum spanning trivial single-file fixes to multi-service cascading leaks with git-history rewriting, complete with a deterministic grading pipeline and an anti-gaming reward function.
17
-
18
- ---
19
-
20
-
21
- ---
22
-
23
-
24
- ## Task Curriculum
25
-
26
- All 13 tasks are defined in `tasks/` with full metadata in each `task.json`. Secret types are detected by `graders/security.py` using regex patterns for AWS keys, GitHub tokens, Firebase keys, connection strings, private keys, SQL passwords, assignment secrets, and base64-encoded variants.
27
-
28
- | ID | Difficulty | Title | Description | Scan Mode | Visibility Tiers | Conflict Map |
29
- |----|-----------|-------|-------------|-----------|-------------------|--------------|
30
- | 1 | Easy | Cloud Provisioning | Hardcoded AWS Access Key in config.py | `dir` | surface, surface, shallow | — |
31
- | 2 | Easy | Database Layer | Password embedded in a raw SQL connection string | `dir` | surface, surface, shallow | — |
32
- | 3 | Easy | Frontend Config | Firebase API key exposed in a client-side config file | `dir` | surface, surface, shallow | — |
33
- | 4 | Easy | System Logging | Debug logging leaks a user token | `dir` | surface, surface, shallow | — |
34
- | 5 | Easy | Git Basics | A tracked .env file leaks credentials in the working tree | `dir` | surface, surface, shallow | — |
35
- | 6 | Medium | Utility Module | A base64-encoded auth token hides in utils.py | `dir` | surface, shallow, deep | — |
36
- | 7 | Medium | CI/CD Pipeline | A deployment workflow prints a secret directly to logs | `dir` | surface, shallow, deep | — |
37
- | 8 | Medium | Noise Filtering | High-entropy dummy values are mixed with one real secret in TOML | `dir` | surface, shallow, deep | — |
38
- | 9 | Medium | DB Migration | A legacy migration embeds administrator credentials | `dir` | surface, shallow, deep | — |
39
- | 10 | Medium | Deployment | A multiline RSA private key is embedded in a shell script | `dir` | surface, shallow, deep | — |
40
- | 11 | Hard | Microservices | The same API key is duplicated across five services | `dir` | surface, deep, cascading | ✓ |
41
- | 12 | Hard | Deep Logic | A secret is embedded as a local variable inside a function | `dir` | surface, deep, cascading | ✓ |
42
- | 13 | Hard | Legacy Audit | A secret was committed in v1.0 and still exists in Git history | `git` | surface, deep, cascading | ✓ |
43
-
44
- **Scan modes**: `dir` scans the working directory only. `git` scans the full git commit history (all revisions), so agents must use `git filter-repo` to clean history — deleting files won't work.
45
-
46
- ---
47
-
48
- ## Secret Visibility Tiers
49
-
50
- Secrets are not all visible at episode start. The environment implements a 4-tier progressive disclosure system defined per-secret in `task.json`:
51
-
52
- | Tier | When Visible | Typical Use |
53
- |------|-------------|-------------|
54
- | `SURFACE` | Immediately on `/reset` | Obvious hardcoded keys in source files |
55
- | `SHALLOW` | After agent calls `inspect_file <path>` | Secrets that require reading the file to notice |
56
- | `DEEP` | After `inspect_git_history` or `inspect_encoded` | Secrets in git commits or base64-encoded blobs |
57
- | `CASCADING` | After a specified trigger secret is fixed | Secrets that only become relevant after another is remediated |
58
-
59
- Hard tasks (11–13) include **conflict maps** that encode dependencies: fixing secret `s1` may *reveal* `s3`, while `s2` may *block* `s3` until resolved.
60
-
61
- ---
62
-
63
- ## Reward Formula
64
-
65
- Defined in `graders/reward.py`. Computed fresh after every `/step`:
66
-
67
- ```
68
- detection_score = (initial_leaks - current_leaks) / initial_leaks
69
- base = 0.4 × detection_score + 0.6 × detection_score # (remediation = detection for now)
70
- health_score = pytest_passed / pytest_total # 0.0 if errors > 0 or total == 0
71
- efficiency = 0.15 × max(0, 1 - steps_taken / step_budget) # decays linearly per step
72
-
73
- if base > 0:
74
- total_reward = min(1.0, base × health_score + efficiency)
75
- else:
76
- total_reward = 0.0 # no free points for doing nothing
77
- ```
78
-
79
- **Key properties:**
80
- - Reward is **0.0 until the agent actually fixes something** — read-only commands like `cat` or `ls` cannot earn reward
81
- - **Health gate**: breaking the test suite (e.g., deleting imports) multiplies reward toward zero
82
- - **Efficiency bonus** (0.0–0.15): rewards agents that solve in fewer steps. Decays to 0 at step budget
83
- - **Step budgets**: Easy = 10, Medium = 20, Hard = 30
84
-
85
- ---
86
-
87
- ## Action Space
88
-
89
- Actions are sent as the `action` field in `POST /step`. Two categories:
90
-
91
- ### Structured Actions (intercepted before bash)
92
-
93
- | Action | Format | Effect |
94
- |--------|--------|--------|
95
- | `inspect_file` | `inspect_file <path>` | Marks file as inspected → unlocks SHALLOW secrets for that path |
96
- | `inspect_git_history` | `inspect_git_history [path]` | Scans git history → unlocks all DEEP secrets requiring git inspection |
97
- | `inspect_encoded` | `inspect_encoded <path> [line]` | Decodes base64 blobs → unlocks DEEP encoded secrets for that path |
98
-
99
- ### Bash Commands (executed in workspace via `/usr/bin/bash -lc`)
100
-
101
- Any string that doesn't match a structured prefix is executed as a bash command in the task workspace. Common patterns:
102
-
103
- - `cat config.py` — read file contents
104
- - `sed -i 's/AKIA.../os.getenv("AWS_KEY")/' config.py` — redact a secret
105
- - `git filter-repo --replace-text <(echo 'ghp_xxx==>REDACTED') --force` — clean git history
106
- - `gitleaks detect --no-git --source .` — run leak scanner
107
-
108
- Commands time out after 90 seconds. Exit code, stdout, and stderr are returned in the observation.
109
-
110
- ---
111
-
112
- ## Observation Keys
113
-
114
- Every `/step` and `/reset` response returns a `session` object with these fields (also listed in `openenv.yaml`):
115
-
116
- | Key | Type | Description |
117
- |-----|------|-------------|
118
- | `visible_secrets` | `list[dict]` | Secrets the agent can currently see (filtered by visibility tier) |
119
- | `hidden_count_hint` | `int` | Number of secrets not yet visible — tells agent more exist |
120
- | `ranked_actions` | `list[dict]` | Top-5 heuristic action suggestions sorted by priority (0.0–1.0) |
121
- | `top_blocker` | `string` | One-sentence description of the highest-priority next action |
122
- | `step_budget` | `int` | Total step budget for this difficulty tier |
123
- | `steps_taken` | `int` | Steps consumed so far |
124
- | `steps_remaining` | `int` | `step_budget - steps_taken` |
125
- | `efficiency_bonus` | `float` | Current efficiency bonus value (decays each step) |
126
- | `conflict_map` | `dict` | Dependency graph between visible secrets (reveals/blocks relationships) |
127
- | `security_score` | `float` | Fraction of initial leaks fixed (0.0–1.0) |
128
- | `health_score` | `float` | Fraction of pytest tests passing (0.0–1.0) |
129
- | `reward` | `float` | Composite reward after this step |
130
- | `observation` | `string` | Combined stdout/stderr from last command + health/security messages |
131
- | `last_result` | `dict` | Raw action, exit_code, stdout, stderr, timed_out from last command |
132
-
133
- ### Ranked Actions
134
-
135
- Generated by `server/observation.py` using 5 heuristics:
136
- 1. **Visible unfixed secrets** → priority 0.92 (fix these first)
137
- 2. **Uninspected high-risk files** → priority based on filename suspicion score
138
- 3. **Git history not yet scanned** → priority 0.75 (medium/hard only)
139
- 4. **Hidden secrets remaining** → priority 0.68 (suggest encoded inspection)
140
- 5. **All visible fixed** → priority 0.85 (run gitleaks validation)
141
-
142
- ---
143
-
144
- ## Quick Start
145
-
146
- ### Local Development
147
-
148
- ```bash
149
- # Install dependencies
150
- pip install -r requirements.txt
151
-
152
- # Generate task workspaces
153
- python tools/generate_tasks.py
154
-
155
- # Start the server
156
- uvicorn server.app:app --host 0.0.0.0 --port 7860
157
-
158
- # Open the debug UI
159
- open http://localhost:7860/web
160
-
161
- # Run the agent (requires LLM API)
162
- export API_BASE_URL="https://openrouter.ai/api/v1"
163
- export HF_TOKEN="your-api-key"
164
- export MODEL_NAME="nvidia/nemotron-3-super-120b-a12b:free"
165
- export ENV_URL="http://localhost:7860"
166
- python inference.py --task-id 1
167
- ```
168
-
169
- ### Docker
170
-
171
- ```bash
172
- docker build -t secretsauditenv .
173
- docker run -p 7860:7860 secretsauditenv
174
- # Server auto-generates tasks and starts on port 7860
175
- ```
176
-
177
- The Dockerfile installs Python 3.11-slim with bash, git, git-filter-repo, and all pip dependencies. The entrypoint runs `tools/generate_tasks.py` then starts uvicorn.
178
-
179
- ---
180
-
181
- ## inference.py — Agent Loop
182
-
183
- The baseline agent (`inference.py`) implements a single-turn ReAct loop over any OpenAI-compatible API:
184
-
185
- 1. **Reset** — `POST /reset` with the target task ID
186
- 2. **Prompt** — Builds a structured prompt from the current session state (reward, leaks, health, last command output, recent actions)
187
- 3. **Call LLM** — Sends prompt to the model, extracts a bash command from the response
188
- 4. **Normalize** — Strips markdown fences, extracts from XML tool_call formats, filters prose prefixes, enforces atomic (no `&&` or `;` chaining)
189
- 5. **Step** — `POST /step` with the action, reads updated state
190
- 6. **Repeat** until `reward >= 1.0` or `MAX_STEPS` (40) reached
191
-
192
- **Environment variables:**
193
-
194
- | Variable | Required | Description |
195
- |----------|----------|-------------|
196
- | `API_BASE_URL` | Yes | OpenAI-compatible API endpoint (e.g., `https://openrouter.ai/api/v1`) |
197
- | `HF_TOKEN` | Yes | API key for the model provider |
198
- | `MODEL_NAME` | Yes | Model identifier (e.g., `nvidia/nemotron-3-super-120b-a12b:free`) |
199
- | `ENV_URL` | No | Server URL, defaults to `http://localhost:7860` |
200
- | `TASK_ID` | No | Default task, overridden by `--task-id` CLI arg |
201
-
202
- **Anti-loop features:**
203
- - Detects 3 consecutive identical actions with identical rewards → injects a CRITICAL WARNING into the prompt and forces a different command
204
- - Filters natural language preambles (e.g., "Let me check...", "Looking at...") before sending to bash
205
-
206
- ---
207
-
208
- ## Grading Pipeline
209
-
210
- ### Security Grader (`graders/security.py`)
211
-
212
- Custom regex-based scanner (no external tools required). Detects:
213
- - AWS Access Keys (`AKIA...`)
214
- - GitHub tokens (`ghp_...`)
215
- - Firebase API keys (`AIza...`)
216
- - Service tokens (`tok_live_...`, `sk_test_...`)
217
- - Private keys (PEM format)
218
- - SQL connection strings (`postgres://user:pass@host/db`)
219
- - SQL passwords (`PASSWORD 'value'`)
220
- - High-entropy assignment secrets (Shannon entropy ≥ 3.2)
221
- - Base64-encoded variants of all the above
222
-
223
- Supports `.gitleaks.toml` allowlists. For `scan_mode: git`, scans all commits via `git rev-list --all`.
224
-
225
- **Anti-gaming**: if an agent deletes `.git`, the grader recovers by creating a fresh snapshot and scanning that — the secret still gets found.
226
-
227
- ### Health Grader (`graders/health.py`)
228
-
229
- Runs `pytest -q --junitxml` in the task workspace and parses the JUnit XML report. Score = `passed / total`. Returns 0.0 if any errors or if pytest times out (60s default).
230
-
231
- ---
232
-
233
- ## Web Debug UI
234
-
235
- Available at `GET /web`. A single-page dark-mode dashboard served from `server/web_ui.html` that lets you:
236
- - Start any of the 13 tasks with one click
237
- - Send structured actions or raw bash commands
238
- - View real-time metrics (reward, leaks, hidden count, steps, efficiency, health)
239
- - See ranked action suggestions and conflict maps
240
- - Browse visible secrets and full observation text
241
- - Review action history
242
-
243
- No external dependencies — pure HTML/CSS/JS.
244
-
245
- ---
246
-
247
- ## Validation
248
-
249
- ```bash
250
- # Run the environment test suite (34 tests)
251
- python -m pytest tests/ -v
252
-
253
- # Run the submission validator (checks connection, Docker build, spec compliance, reward integrity)
254
- bash validate-submission.sh
255
- ```
256
-
257
- The validator checks:
258
- 1. **Connection** — `/reset` returns HTTP 200
259
- 2. **Docker portability** — no absolute host paths leak into the image
260
- 3. **Spec compliance** — `spec.md` exists, all 13 task directories present, `openenv validate` passes
261
- 4. **Reward integrity** — smoke test runs `inference.py` for 2 steps and verifies `[START]/[STEP]/[END]` log format
262
-
263
- ---
264
-
265
- ## Project Structure
266
-
267
- ```
268
- .
269
- ├── server/
270
- │ ├── app.py # FastAPI routes (/reset, /step, /state, /tasks, /web)
271
- │ ├── environment.py # Core environment logic, visibility tiers, action parsing
272
- │ ├── observation.py # Ranked action heuristics and top_blocker computation
273
- │ └── web_ui.html # Debug dashboard (served at /web)
274
- ├── graders/
275
- │ ├── security.py # Regex-based secret scanner with git history support
276
- │ ├── health.py # Pytest-based health grader with JUnit parsing
277
- │ ├── reward.py # Composite reward: security × health + efficiency
278
- │ ├── gitleaks_eval.py # Spec-aligned wrapper with git integrity reporting
279
- │ └── health_eval.py # Spec-aligned wrapper with failure messaging
280
- ├── tasks/
281
- │ ├── easy/task_01..05/ # 5 easy tasks (single-file, surface+shallow secrets)
282
- │ ├── medium/task_06..10/ # 5 medium tasks (multi-format, surface+shallow+deep)
283
- │ └── hard/task_11..13/ # 3 hard tasks (cascading, conflict maps, git history)
284
- ├── tests/
285
- │ ├── test_hidden_leaks.py # 11 tests: visibility tier logic
286
- │ ├── test_ranked_actions.py # 12 tests: heuristic action suggestions
287
- │ └── test_reward.py # 11 tests: reward formula and efficiency bonus
288
- ├── tools/
289
- │ ├── generate_tasks.py # Generates all 13 task workspaces with seeded secrets
290
- │ ├── check_space_ready.py
291
- │ ├── prepare_hf_space_bundle.sh
292
- │ └── prepare_github_upload_bundle.sh
293
- ├── inference.py # Baseline LLM agent loop (OpenAI-compatible)
294
- ├── openenv.yaml # OpenEnv spec declaration
295
- ├── Dockerfile # Python 3.11-slim + git + git-filter-repo
296
- ├── hf_space_entrypoint.sh # Docker entrypoint: generate tasks → start uvicorn
297
- ├── validate-submission.sh # 4-check submission validator
298
- ├── requirements.txt # Pip dependencies
299
- ├── pyproject.toml # Package metadata
300
- └── spec.md # Environment specification document
301
- ```
302
-
303
- ---
304
-
305
- ## License
306
-
307
- MIT
 
4
  colorFrom: indigo
5
  colorTo: red
6
  sdk: docker
7
+ app_port: 7860
8
+ pinned: true
9
+ tags:
10
+ - openenv
11
+ - reinforcement-learning
12
+ - secret-detection
13
+ - cybersecurity
14
+ - benchmark
15
+ - ai-safety
16
  ---
17
 
18
  # SecretsAuditEnv
19
 
20
+ A 13-task RL benchmark for AI agents that find and fix secret leaks in git-backed codebases.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
openenv.yaml CHANGED
@@ -1,74 +1,126 @@
1
- version: "1.0"
2
- spec_version: 1
3
- name: "secrets_audit_env"
4
- description: "A 13-task RL benchmark for AI agents that find and fix secret leaks in git-backed codebases."
5
- type: space
6
- runtime: fastapi
7
- app: server.app:app
8
- port: 7860
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  tasks:
11
  - id: task_1
12
- name: "Cloud Provisioning"
13
- description: "Hardcoded AWS Access Key in config.py."
14
- difficulty: "easy"
 
15
 
16
  - id: task_2
17
- name: "Database Layer"
18
- description: "Password embedded in a raw SQL connection string."
19
- difficulty: "easy"
 
20
 
21
  - id: task_3
22
- name: "Frontend Config"
23
- description: "Firebase API key exposed in a client-side config file."
24
- difficulty: "easy"
 
25
 
26
  - id: task_4
27
- name: "System Logging"
28
- description: "Debug logging leaks a user token."
29
- difficulty: "easy"
 
30
 
31
  - id: task_5
32
- name: "Git Basics"
33
- description: "A tracked .env file leaks credentials in the working tree."
34
- difficulty: "easy"
 
35
 
36
  - id: task_6
37
- name: "Utility Module"
38
- description: "A base64-encoded auth token hides in utils.py."
39
- difficulty: "medium"
 
40
 
41
  - id: task_7
42
- name: "CI/CD Pipeline"
43
- description: "A deployment workflow prints a secret directly to logs."
44
- difficulty: "medium"
 
45
 
46
  - id: task_8
47
- name: "Noise Filtering"
48
- description: "High-entropy dummy values are mixed with one real secret in TOML."
49
- difficulty: "medium"
 
50
 
51
  - id: task_9
52
- name: "DB Migration"
53
- description: "A legacy migration embeds administrator credentials."
54
- difficulty: "medium"
 
55
 
56
  - id: task_10
57
- name: "Deployment"
58
- description: "A multiline RSA private key is embedded in a shell script."
59
- difficulty: "medium"
 
60
 
61
  - id: task_11
62
- name: "Microservices"
63
- description: "The same API key is duplicated across five services."
64
- difficulty: "hard"
 
65
 
66
  - id: task_12
67
- name: "Deep Logic"
68
- description: "A secret is embedded as a local variable inside a function."
69
- difficulty: "hard"
 
70
 
71
  - id: task_13
72
- name: "Legacy Audit"
73
- description: "A secret was committed in v1.0 and still exists in Git history."
74
- difficulty: "hard"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: secrets-audit-env
2
+ description: |
3
+ A 13-task RL benchmark for AI agents that find and fix secret leaks
4
+ in git-backed codebases. Agents interact via bash commands and
5
+ structured inspection actions, graded on security, code health,
6
+ and efficiency.
 
 
7
 
8
+ Three difficulty tiers (easy → medium → hard) with deterministic
9
+ per-episode graders.
10
+
11
+ version: 1.0.0
12
+ author: Team R2X
13
+ license: MIT
14
+
15
+ # OpenEnv configuration
16
+ openenv:
17
+ env_type: custom
18
+
19
+ server:
20
+ port: 7860
21
+ host: 0.0.0.0
22
+
23
+ # Required OpenEnv endpoints
24
+ required_endpoints:
25
+ tasks: GET /tasks
26
+ grader: POST /grader
27
+ baseline: POST /baseline
28
+
29
+ entry_points:
30
+ server: server.app:app
31
+
32
+ # Tasks (easy → medium → hard)
33
  tasks:
34
  - id: task_1
35
+ name: Cloud Provisioning
36
+ difficulty: easy
37
+ description: >
38
+ Hardcoded AWS Access Key in config.py.
39
 
40
  - id: task_2
41
+ name: Database Layer
42
+ difficulty: easy
43
+ description: >
44
+ Password embedded in a raw SQL connection string.
45
 
46
  - id: task_3
47
+ name: Frontend Config
48
+ difficulty: easy
49
+ description: >
50
+ Firebase API key exposed in a client-side config file.
51
 
52
  - id: task_4
53
+ name: System Logging
54
+ difficulty: easy
55
+ description: >
56
+ Debug logging leaks a user token.
57
 
58
  - id: task_5
59
+ name: Git Basics
60
+ difficulty: easy
61
+ description: >
62
+ A tracked .env file leaks credentials in the working tree.
63
 
64
  - id: task_6
65
+ name: Utility Module
66
+ difficulty: medium
67
+ description: >
68
+ A base64-encoded auth token hides in utils.py.
69
 
70
  - id: task_7
71
+ name: CI/CD Pipeline
72
+ difficulty: medium
73
+ description: >
74
+ A deployment workflow prints a secret directly to logs.
75
 
76
  - id: task_8
77
+ name: Noise Filtering
78
+ difficulty: medium
79
+ description: >
80
+ High-entropy dummy values are mixed with one real secret in TOML.
81
 
82
  - id: task_9
83
+ name: DB Migration
84
+ difficulty: medium
85
+ description: >
86
+ A legacy migration embeds administrator credentials.
87
 
88
  - id: task_10
89
+ name: Deployment
90
+ difficulty: medium
91
+ description: >
92
+ A multiline RSA private key is embedded in a shell script.
93
 
94
  - id: task_11
95
+ name: Microservices
96
+ difficulty: hard
97
+ description: >
98
+ The same API key is duplicated across five services.
99
 
100
  - id: task_12
101
+ name: Deep Logic
102
+ difficulty: hard
103
+ description: >
104
+ A secret is embedded as a local variable inside a function.
105
 
106
  - id: task_13
107
+ name: Legacy Audit
108
+ difficulty: hard
109
+ description: >
110
+ A secret was committed in v1.0 and still exists in Git history.
111
+
112
+ # Dependencies
113
+ dependencies:
114
+ - openenv-core>=0.2.0
115
+ - fastapi>=0.100.0
116
+ - uvicorn>=0.23.0
117
+ - requests>=2.31.0
118
+ - openai>=1.0.0
119
+
120
+ # Tags for discovery
121
+ tags:
122
+ - secret-detection
123
+ - cybersecurity
124
+ - rl-environment
125
+ - code-security
126
+ - benchmark
server/environment.py CHANGED
@@ -124,7 +124,11 @@ class SecretsAuditEnvironment:
124
  tasks: list[dict[str, Any]] = []
125
  for task_file in sorted(self.tasks_root.glob("*/task_*/task.json")):
126
  with task_file.open("r", encoding="utf-8") as handle:
127
- tasks.append(json.load(handle))
 
 
 
 
128
  return tasks
129
 
130
  def state(self) -> dict[str, Any]:
 
124
  tasks: list[dict[str, Any]] = []
125
  for task_file in sorted(self.tasks_root.glob("*/task_*/task.json")):
126
  with task_file.open("r", encoding="utf-8") as handle:
127
+ task_data = json.load(handle)
128
+ # Add task_id field for OpenEnv compatibility
129
+ task_num = task_data.get("id", 0)
130
+ task_data["task_id"] = f"task_{task_num}"
131
+ tasks.append(task_data)
132
  return tasks
133
 
134
  def state(self) -> dict[str, Any]: