OpenSecOpsEnv2 / docs /analysis_and_next_steps.md
SapphireGaze429's picture
Please work
b595345
|
Raw
History Blame Contribute Delete
13.4 kB
# 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:
1. **`_drift_metrics()`** β€” Brownian drift + scenario-specific escalation:
- Memory leak: `memory += 1.5/step`, `latency += 10/step` per affected svc
- DDoS: `cpu += attack_progress Γ— 5`, `latency += attack_progress Γ— 100`
- Exfiltration: `cpu += attack_progress Γ— 1.5`, `memory += attack_progress Γ— 0.8`
2. **`_evolve_attack()`** β€” `attack_progress += 0.08/step` (Γ—0.5 if an affected service is isolated)
3. **Mitigation side-effects** (when correct action taken):
- `restart_service` β†’ resets memory to 35%, latency to 80ms
- `block_ip` β†’ reduces affected svc cpu/latency, attack_progress βˆ’0.2
- `isolate_service` β†’ attack_progress βˆ’0.35
- `scale_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).
```python
# 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:
```python
# 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.
```python
# 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_config` or `infra_failure:service_crash` scenario using `rollback_deployment` action (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:
1. Add explicit instruction: *"When investigating, always check ALL services in the topology, not just the most obvious one"*
2. Add: *"The gateway / frontend service is rarely the root cause; look at the backend services it calls"*
3. Add: *"You MUST call `run_security_scan` on 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:latest` and verify `/health` returns 200
- [ ] `curl -X POST http://localhost:8000/reset -d '{}' -H 'Content-Type: application/json'` returns observation
- [ ] Set `HF_TOKEN` and run `python inference.py` β€” verify 3Γ— `[START]`/`[STEP]`/`[END]` blocks print
- [ ] Push to HF Spaces with correct `README.md` `sdk: docker` header
- [ ] Set Space secrets: `API_BASE_URL`, `MODEL_NAME`, `HF_TOKEN`
- [ ] Ping `https://your-space.hf.space/reset` with POST β€” verify 200
### HF Spaces `README.md` header (required at top of HF repo README):
```yaml
---
title: OpenSecOpsEnv
emoji: πŸ”
colorFrom: blue
colorTo: green
sdk: docker
app_port: 8000
tags:
- openenv
- reinforcement-learning
- secops
- agent-evaluation
---
```