Spaces:
Sleeping
OpenSecOpsEnv β Full Audit, MDP Definition & Next Steps
1 Β· Full MDP Definition
This is the formal Markov Decision Process that your environment implements.
State Space S
The hidden state (never given to the agent directly) is:
| Variable | Type | Description |
|---|---|---|
true_root_cause |
str |
"infra_failure" or "cyber_attack" |
subtype |
str |
"memory_leak", "ddos", "data_exfiltration" |
affected_services |
list[str] |
Services that are actually compromised |
attack_progress |
float β [0,1] |
How far the attack/failure has progressed |
noise_level |
float β [0,1] |
Fraction of log/alert signals that are misleading |
metrics[svc] |
dict |
Per-service {cpu, memory, latency, error_rate} |
isolated_services |
set[str] |
Services the agent has isolated |
blocked_ips |
set[str] |
IPs the agent has blocked |
step_count |
int |
Current episode step |
The observation (what the agent actually sees) is a stochastic projection of the hidden state:
O = f(S) + noise
= {alerts, metrics_snapshot, partial_logs, topology, last_action_result, time_step}
Action Space A
Discrete (9 actions), parameterized:
| Action | Parameters | Class |
|---|---|---|
query_logs |
{service} |
Investigation |
inspect_metrics |
{service?} |
Investigation |
run_security_scan |
{target} |
Investigation |
restart_service |
{service} |
Mitigation |
scale_service |
{service, replicas} |
Mitigation |
block_ip |
{ip} |
Mitigation |
rollback_deployment |
{service, version} |
Mitigation |
isolate_service |
{service} |
Mitigation |
submit_diagnosis |
{label} |
Terminal |
Transition Function T(s, a) β s'
State evolves deterministically (seeded RNG) after each action:
_drift_metrics()β Brownian drift + scenario-specific escalation:- Memory leak:
memory += 1.5/step,latency += 10/stepper affected svc - DDoS:
cpu += attack_progress Γ 5,latency += attack_progress Γ 100 - Exfiltration:
cpu += attack_progress Γ 1.5,memory += attack_progress Γ 0.8
- Memory leak:
_evolve_attack()βattack_progress += 0.08/step(Γ0.5 if an affected service is isolated)Mitigation side-effects (when correct action taken):
restart_serviceβ resets memory to 35%, latency to 80msblock_ipβ reduces affected svc cpu/latency, attack_progress β0.2isolate_serviceβ attack_progress β0.35scale_serviceβ cpu β20%, latency β200ms
Reward Function R(s, a) β β
Dense per-step reward β [β1.0, +1.0]:
Investigation on affected service β +0.2
inspect_metrics({}) (global) β +0.2 (always useful)
run_security_scan on affected + cyber β +0.3
Correct mitigation β +0.5
Correct submit_diagnosis β +1.0
Investigation on NON-affected svc β β0.05
Ineffective mitigation β β0.1
Wrong service (not in metrics) β β0.2
Harmful action (wrong ip/isolate) β β0.5
Wrong submit_diagnosis β β1.0
Terminal Condition
Episode ends when:
- Agent calls
submit_diagnosis(always terminates, reward Β±1.0), OR step_count >= max_steps(30 / 40 / 50 per task)
Grader G(episode) β [0,1]
score = 0.5 Γ diagnosis_correct
+ 0.3 Γ action_efficiency
+ 0.2 Γ investigation_quality
diagnosis_correct = 1.0 (exact) | 0.5 (category) | 0.0
action_efficiency = 0.7 Γ mitigation_recall + 0.3 Γ step_bonus
mitigation_recall = |done β© correct| / |correct|
step_bonus = min(1, ideal_steps / step_count) ideal = max(n_correctΓ3, 5)
investigation_quality = |investigated_affected| / |affected|
2 Β· Gap Analysis vs Competition Rubric
Real-world utility (30%) β Current: ~25/30 β Target: 28/30
| Issue | Impact | Fix? |
|---|---|---|
| Only 3 scenario types (memory_leak, DDoS, exfil) | Medium | Add 4th task type |
| False-alert signal in HARD task is labeled "FALSE POSITIVE" in the alert text itself | Medium | Remove the self-labeling hint |
| gateway not treated as a valid investigation target (penalized) | Low-Med | See Β§3-B |
Task & grader quality (25%) β Current: ~20/25 β Target: 24/25
| Issue | Impact | Fix? |
|---|---|---|
run_security_scan counted as investigation not mitigation β but HARD task lists it in correct_mitigations. Results in the agent never getting credit for scans even when done. |
Critical | Β§3-A |
Hard task: affected_services = ["db","auth"], but agent gets no IQ credit for scanning β only for query_logs/inspect_metrics. run_security_scan:db should count toward investigation_quality |
High | Β§3-A |
grader step_bonus uses ideal_steps = max(n_correctΓ3, 5) β for easy task with 1 mitigation this gives ideal=5 but optimal is 4 steps. Slightly penalizes perfect play |
Low | Β§3-C |
Environment design (20%) β Current: ~17/20 β Target: 19/20
| Issue | Impact | Fix? |
|---|---|---|
inspect_metrics({}) gives same +0.2 as targeted inspect. No penalty for already-seen services |
Low | Cosmetic |
_generate_logs() called twice per step (in _build_observation and in _act_query_logs) β same pool, different random shuffle |
Low | Β§3-D |
No cooldown on repeat actions β agent can query_logs:auth 20Γ for +4.0 reward with no diminishing returns |
Medium | Β§3-E |
Code quality & spec compliance (15%) β Current: ~13/15 β Target: 15/15
| Issue | Impact | Fix? |
|---|---|---|
score in log_end() formatted as :.2f β spec says 2 decimal places, this is fine |
None | β |
openenv.yaml lists run_security_scan under correct_mitigations for HARD task, but grader never counts it as mitigation |
Minor | Β§3-A |
No LICENSE file despite README saying MIT |
Low | Β§3-F |
Docker HEALTHCHECK hits /health β β good |
β | β |
inference.py falls back to heuristic when no LLM key β β good |
β | β |
Creativity & novelty (10%) β Current: ~8/10 β Target: 9/10
| Issue | Impact | Fix? |
|---|---|---|
| The cache false-alert says "FALSE POSITIVE" in the message text β removes the discovery challenge | Medium | Β§3-B |
| Adding a 4th task would add novelty | Medium | Β§3-G (optional) |
3 Β· Prioritized Fixes (High β Low)
A Β· [CRITICAL] Fix run_security_scan in HARD grader β grader.py + env.py
Problem: run_security_scan:db is listed in correct_mitigations for the hard task (openenv.yaml line 143-144), but INVESTIGATION_ACTIONS in env.py means it's never appended to state.mitigation_actions β only to state.investigation_actions. The grader only counts mitigation_actions toward mitigation_recall. So an agent doing the right scans gets 0 mitigation credit.
Fix in grader.py: Count security scans listed in correct_mitigations as valid β check both mitigation_actions and investigation_actions whose keys appear in correct_mitigations.
Also fix in grader.py: Let run_security_scan:X count toward investigation_quality for service X (already works because investigation_actions includes them, but the set intersection logic uses parts[1] which gives the target correctly β this part is actually fine).
# In grade(), replace mitigation recall calculation:
# Check BOTH lists for items that appear in correct_mitigations
all_taken_actions = set(mitigation_actions) | set(investigation_actions)
n_correct = len(all_taken_actions & set(correct_mitigations))
B Β· [HIGH] Remove self-labeling hint from HARD task alert β task_definitions.py
Problem: The false-alert message says "(FALSE POSITIVE)" in the text. This tells the agent exactly that it's a false alarm, defeating the point of the noise.
Fix in task_definitions.py: Change:
# Before
"message": "Cache memory 82% β possible memory leak (FALSE POSITIVE)"
# After
"message": "Cache memory 82% β triggering high-memory threshold policy"
C Β· [MEDIUM] Fix step_bonus for easy task β grader.py
Problem: ideal_steps = max(n_correct * 3, 5) gives 5 for easy task (1 correct mitigation Γ 3 = 3, max with 5 = 5). But the optimal trajectory is 4 steps (inspect, query, restart, submit). An agent doing it perfectly in 4 steps gets step_bonus = 5/4 = 1.25 β clamped to 1.0 β still OK. For medium: 3 Γ 3 = 9, optimal is 7 β fine. This is actually acceptable, just add a note.
D Β· [MEDIUM] Prevent log double-generation and add repeat-action diminishing returns β env.py
Problem: When query_logs is called, _act_query_logs calls _generate_logs() and then _build_observation also calls _generate_logs() again. Two different shuffles, slightly incoherent. Fix by building the observation first with the same log pool.
Also: An agent can harvest +0.2 per step by repeatedly calling query_logs:auth on the affected service. Add a per-service "already investigated" diminishing return.
Fix in env.py: Maintain a _investigated: dict[str, int] counter. First time: full reward. Second time same service: +0.05. Third+ time: 0.
# In __init__:
self._investigated: dict[str, int] = {}
# In _act_query_logs / _act_inspect_metrics:
count = self._investigated.get(svc, 0)
self._investigated[svc] = count + 1
if svc in self._hidden.affected_services:
reward = 0.2 if count == 0 else (0.05 if count == 1 else 0.0)
E Β· [LOW] Add LICENSE file β root
Create a LICENSE file with the MIT license text. Required for open-source credibility and referenced by README.
F Β· [LOW / OPTIONAL] Add a 4th task β task_definitions.py + openenv.yaml
A medium_hard task such as a bad deployment rollback scenario would:
- Fill the gap between medium (0.73) and hard (0.795) β scores are surprisingly close
- Add a
misconfiguration:bad_configorinfra_failure:service_crashscenario usingrollback_deploymentaction (currently never the correct mitigation in any task!)
This is optional but would increase creativity score and make rollback_deployment useful.
4 Β· Files to Edit (Summary Table)
| File | Change | Priority |
|---|---|---|
opensecops_env/grader.py |
Fix mitigation_recall to include investigation_actions β© correct_mitigations | π΄ Critical |
opensecops_env/tasks/task_definitions.py |
Remove "(FALSE POSITIVE)" from hard task alert text | π High |
opensecops_env/env.py |
Add diminishing returns for repeat investigation on same service | π‘ Medium |
opensecops_env/env.py |
Fix double log generation (minor) | π‘ Medium |
openenv.yaml |
Clarify that run_security_scan mitigations in HARD task are also graded as investigation | π‘ Medium |
LICENSE |
Add MIT license text | π’ Low |
README.md |
Update baseline scores to actual measured values (1.00, 0.73, 0.795) | π’ Low |
opensecops_env/tasks/task_definitions.py |
(Optional) Add 4th task | π΅ Optional |
5 Β· Should You Fine-tune?
No, you do not need to fine-tune any model. Your environment is the submission, not the model.
The competition evaluates your environment quality β judges will run their own models against it. The inference script produces a baseline score that shows the environment is solvable.
What you should optimize instead:
| Concern | What to do |
|---|---|
| Baseline score too low | Improve the system prompt in inference.py β more explicit strategy hints |
| Baseline score too high | Make tasks harder (more noise, more red herrings) |
| Scores not deterministic | Ensure _rng is seeded before EVERY _generate_logs call |
| Runtime > 20min | MAX_STEPS = 20 already set β keep it; 3 tasks Γ 20 steps Γ ~1s/LLM call β 1 min |
System prompt improvements to inference.py that would raise the baseline score:
- Add explicit instruction: "When investigating, always check ALL services in the topology, not just the most obvious one"
- Add: "The gateway / frontend service is rarely the root cause; look at the backend services it calls"
- Add: "You MUST call
run_security_scanon suspicious services before submitting if you suspect a cyber attack"
6 Β· Deployment Checklist (Before Submitting to HF Spaces)
- Run
docker build -t opensecops-env:latest .locally β (user is doing this now) - Run
docker run -p 8000:8000 opensecops-env:latestand verify/healthreturns 200 -
curl -X POST http://localhost:8000/reset -d '{}' -H 'Content-Type: application/json'returns observation - Set
HF_TOKENand runpython inference.pyβ verify 3Γ[START]/[STEP]/[END]blocks print - Push to HF Spaces with correct
README.mdsdk: dockerheader - Set Space secrets:
API_BASE_URL,MODEL_NAME,HF_TOKEN - Ping
https://your-space.hf.space/resetwith POST β verify 200
HF Spaces README.md header (required at top of HF repo README):
---
title: OpenSecOpsEnv
emoji: π
colorFrom: blue
colorTo: green
sdk: docker
app_port: 8000
tags:
- openenv
- reinforcement-learning
- secops
- agent-evaluation
---