hirann commited on
Commit
f8ed336
Β·
verified Β·
1 Parent(s): 1a59270

Upload immunoorg/agents/defender.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. immunoorg/agents/defender.py +165 -165
immunoorg/agents/defender.py CHANGED
@@ -1,165 +1,165 @@
1
- """
2
- Defender Agent
3
- ==============
4
- The primary LLM-driven agent that detects, contains, analyzes, and restructures.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- DEFENDER_SYSTEM_PROMPT = """You are the Chief Incident Response Officer of a simulated enterprise called ImmunoOrg.
10
-
11
- You observe network telemetry and organizational structure in real-time. Your mission spans five phases:
12
-
13
- 1. **DETECTION**: Analyze logs, traffic patterns, and anomalies to identify active cyber-attacks.
14
- 2. **CONTAINMENT**: Take tactical actions (block ports, isolate nodes, quarantine traffic) to stop the attack from spreading.
15
- 3. **ROOT CAUSE ANALYSIS**: Correlate technical failures (e.g., SQL injection on a database) to organizational weaknesses (e.g., no DevSecOps integration, siloed departments).
16
- 4. **ORG REFACTOR**: Restructure the organizational graph to eliminate systemic vulnerabilities β€” merge departments, create shortcut communication channels, reduce bureaucracy.
17
- 5. **VALIDATION**: Verify that your changes improved resilience and the system is secure.
18
-
19
- ## CRITICAL CONSTRAINTS
20
- - Every tactical action (block_port, isolate_node, etc.) requires APPROVAL from department heads.
21
- - Department heads have CONFLICTING priorities (IT wants uptime, Security wants lockdown, Engineering wants velocity).
22
- - Approval flows through the organizational graph β€” if there are silos (missing connections), approvals are SLOW or IMPOSSIBLE.
23
- - The adversary ADAPTS to your actions. If you block one vector, they'll pivot.
24
-
25
- ## OUTPUT FORMAT
26
- Respond with a JSON object:
27
- ```json
28
- {
29
- "action_type": "tactical|strategic|diagnostic",
30
- "tactical_action": "block_port|isolate_node|scan_logs|...",
31
- "strategic_action": "merge_departments|create_shortcut_edge|...",
32
- "diagnostic_action": "correlate_failure|identify_silo|...",
33
- "target": "<node_id or department_id>",
34
- "secondary_target": "<optional, for merge/link operations>",
35
- "parameters": {},
36
- "reasoning": "<Your detailed chain-of-thought reasoning>"
37
- }
38
- ```
39
-
40
- ## STRATEGY TIPS
41
- - In DETECTION phase: Use scan_logs and trace_attack_path to understand the situation
42
- - In CONTAINMENT: Prioritize isolating compromised nodes, but be aware of downtime costs
43
- - In RCA: Use correlate_failure and identify_silo to build your world model
44
- - In REFACTOR: Address root causes β€” if security and engineering are siloed, create a shortcut edge
45
- - Think about BOTH technical AND organizational dimensions simultaneously
46
- - Your reasoning quality is scored β€” explain WHY you take each action
47
- """
48
-
49
- DEFENDER_FEW_SHOT_EXAMPLES = [
50
- {
51
- "observation_summary": "Web server web-server-01 shows anomalous SQL query patterns on port 3306. Threat level: 0.4. Phase: DETECTION.",
52
- "response": {
53
- "action_type": "diagnostic",
54
- "diagnostic_action": "scan_logs",
55
- "target": "web-server-01",
56
- "reasoning": "The anomalous SQL patterns on port 3306 suggest a potential SQL injection attack. I need to scan the logs first to confirm the attack vector and understand the scope before taking containment action. Premature containment without evidence could cause unnecessary downtime."
57
- }
58
- },
59
- {
60
- "observation_summary": "Confirmed SQL injection on db-server-01 via port 3306. Lateral movement detected to app-server-02. Threat level: 0.7. Phase: CONTAINMENT.",
61
- "response": {
62
- "action_type": "tactical",
63
- "tactical_action": "isolate_node",
64
- "target": "db-server-01",
65
- "reasoning": "The SQL injection on db-server-01 is confirmed and has already spread laterally to app-server-02. Priority is to isolate the source node (db-server-01) immediately to prevent further lateral movement. The data tier is critical, but the active breach poses a greater risk than temporary downtime. I'll address app-server-02 in the next step."
66
- }
67
- },
68
- {
69
- "observation_summary": "Attack contained. Belief map shows SQL injection correlated with missing DevSecOps. Security and Engineering departments have no direct communication channel (SILO). Phase: RCA.",
70
- "response": {
71
- "action_type": "diagnostic",
72
- "diagnostic_action": "identify_silo",
73
- "target": "dept-security",
74
- "reasoning": "The SQL injection succeeded because there's no DevSecOps integration β€” Security can't review Engineering's code before deployment. The root cause is organizational: Security and Engineering are siloed with no direct communication channel. I need to confirm this silo before proposing a structural fix."
75
- }
76
- },
77
- ]
78
-
79
-
80
- def get_defender_prompt() -> str:
81
- """Get the full defender system prompt."""
82
- return DEFENDER_SYSTEM_PROMPT
83
-
84
-
85
- def get_few_shot_examples() -> list[dict]:
86
- """Get few-shot examples for the defender agent."""
87
- return DEFENDER_FEW_SHOT_EXAMPLES
88
-
89
-
90
- def format_observation_for_llm(observation: dict) -> str:
91
- """Format an observation into a human-readable prompt for the LLM."""
92
- parts = []
93
-
94
- parts.append(f"## Current Phase: {observation.get('current_phase', 'unknown').upper()}")
95
- parts.append(f"Step: {observation.get('step_count', 0)} | Sim Time: {observation.get('sim_time', 0):.1f}")
96
- parts.append(f"Threat Level: {observation.get('threat_level', 0):.2f}")
97
- parts.append(f"System Downtime: {observation.get('system_downtime', 0):.1f}")
98
-
99
- # Network health
100
- health = observation.get("network_health_summary", {})
101
- if health:
102
- parts.append("\n## Network Health")
103
- for tier, h in health.items():
104
- status = "🟒" if h > 0.8 else "🟑" if h > 0.5 else "πŸ”΄"
105
- parts.append(f" {status} {tier}: {h:.0%}")
106
-
107
- # Detected attacks
108
- attacks = observation.get("detected_attacks", [])
109
- if attacks:
110
- parts.append(f"\n## Active Threats ({len(attacks)})")
111
- for atk in attacks:
112
- parts.append(f" ⚠️ {atk.get('vector', '?')} on {atk.get('target_node', '?')} "
113
- f"(severity: {atk.get('severity', 0):.2f})")
114
-
115
- # Recent logs
116
- logs = observation.get("recent_logs", [])
117
- if logs:
118
- parts.append(f"\n## Recent Logs ({len(logs)})")
119
- for log in logs[-5:]:
120
- indicator = "🚨" if log.get("attack_indicator") else "πŸ“‹"
121
- parts.append(f" {indicator} [{log.get('severity', 'info')}] {log.get('message', '')}")
122
-
123
- # Org structure
124
- org_nodes = observation.get("org_nodes", [])
125
- if org_nodes:
126
- parts.append(f"\n## Organization ({len(org_nodes)} departments)")
127
- for dept in org_nodes:
128
- parts.append(f" 🏒 {dept.get('name', '?')} β€” trust: {dept.get('trust_score', 0):.2f}, "
129
- f"latency: {dept.get('response_latency', 0):.1f}")
130
-
131
- # Pending approvals
132
- approvals = observation.get("pending_approvals", [])
133
- if approvals:
134
- parts.append(f"\n## Pending Approvals ({len(approvals)})")
135
- for apr in approvals:
136
- parts.append(f" ⏳ {apr.get('action_name', '?')} β†’ {apr.get('approver', '?')} "
137
- f"(status: {apr.get('status', '?')})")
138
-
139
- # Action result
140
- result = observation.get("action_result", "")
141
- if result:
142
- success = "βœ…" if observation.get("action_success") else "❌"
143
- parts.append(f"\n## Last Action Result: {success} {result}")
144
-
145
- # Belief map feedback
146
- feedback = observation.get("belief_map_feedback", "")
147
- if feedback:
148
- parts.append(f"\n## World Model Feedback: {feedback}")
149
-
150
- # Alerts
151
- alerts = observation.get("alerts", [])
152
- if alerts:
153
- parts.append("\n## Alerts & Intelligence")
154
- for alert in alerts:
155
- parts.append(f" πŸ”” {alert}")
156
-
157
- # Board Directives
158
- directives = observation.get("directives", [])
159
- if directives:
160
- parts.append("\n## πŸ‘” Board Directives (MUST FOLLOW)")
161
- for d in directives:
162
- parts.append(f" πŸ“Œ {d}")
163
-
164
- return "\n".join(parts)
165
-
 
1
+ """
2
+ Defender Agent
3
+ ==============
4
+ The primary LLM-driven agent that detects, contains, analyzes, and restructures.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ DEFENDER_SYSTEM_PROMPT = """You are the Chief Incident Response Officer of a simulated enterprise called ImmunoOrg.
10
+
11
+ You observe network telemetry and organizational structure in real-time. Your mission spans five phases:
12
+
13
+ 1. **DETECTION**: Analyze logs, traffic patterns, and anomalies to identify active cyber-attacks.
14
+ 2. **CONTAINMENT**: Take tactical actions (block ports, isolate nodes, quarantine traffic) to stop the attack from spreading.
15
+ 3. **ROOT CAUSE ANALYSIS**: Correlate technical failures (e.g., SQL injection on a database) to organizational weaknesses (e.g., no DevSecOps integration, siloed departments).
16
+ 4. **ORG REFACTOR**: Restructure the organizational graph to eliminate systemic vulnerabilities β€” merge departments, create shortcut communication channels, reduce bureaucracy.
17
+ 5. **VALIDATION**: Verify that your changes improved resilience and the system is secure.
18
+
19
+ ## CRITICAL CONSTRAINTS
20
+ - Every tactical action (block_port, isolate_node, etc.) requires APPROVAL from department heads.
21
+ - Department heads have CONFLICTING priorities (IT wants uptime, Security wants lockdown, Engineering wants velocity).
22
+ - Approval flows through the organizational graph β€” if there are silos (missing connections), approvals are SLOW or IMPOSSIBLE.
23
+ - The adversary ADAPTS to your actions. If you block one vector, they'll pivot.
24
+
25
+ ## OUTPUT FORMAT
26
+ Respond with a JSON object:
27
+ ```json
28
+ {
29
+ "action_type": "tactical|strategic|diagnostic",
30
+ "tactical_action": "block_port|isolate_node|scan_logs|...",
31
+ "strategic_action": "merge_departments|create_shortcut_edge|...",
32
+ "diagnostic_action": "correlate_failure|identify_silo|...",
33
+ "target": "<node_id or department_id>",
34
+ "secondary_target": "<optional, for merge/link operations>",
35
+ "parameters": {},
36
+ "reasoning": "<Your detailed chain-of-thought reasoning>"
37
+ }
38
+ ```
39
+
40
+ ## STRATEGY TIPS
41
+ - In DETECTION phase: Use scan_logs and trace_attack_path to understand the situation
42
+ - In CONTAINMENT: Prioritize isolating compromised nodes, but be aware of downtime costs
43
+ - In RCA: Use correlate_failure and identify_silo to build your world model
44
+ - In REFACTOR: Address root causes β€” if security and engineering are siloed, create a shortcut edge
45
+ - Think about BOTH technical AND organizational dimensions simultaneously
46
+ - Your reasoning quality is scored β€” explain WHY you take each action
47
+ """
48
+
49
+ DEFENDER_FEW_SHOT_EXAMPLES = [
50
+ {
51
+ "observation_summary": "Web server web-server-01 shows anomalous SQL query patterns on port 3306. Threat level: 0.4. Phase: DETECTION.",
52
+ "response": {
53
+ "action_type": "diagnostic",
54
+ "diagnostic_action": "scan_logs",
55
+ "target": "web-server-01",
56
+ "reasoning": "The anomalous SQL patterns on port 3306 suggest a potential SQL injection attack. I need to scan the logs first to confirm the attack vector and understand the scope before taking containment action. Premature containment without evidence could cause unnecessary downtime."
57
+ }
58
+ },
59
+ {
60
+ "observation_summary": "Confirmed SQL injection on db-server-01 via port 3306. Lateral movement detected to app-server-02. Threat level: 0.7. Phase: CONTAINMENT.",
61
+ "response": {
62
+ "action_type": "tactical",
63
+ "tactical_action": "isolate_node",
64
+ "target": "db-server-01",
65
+ "reasoning": "The SQL injection on db-server-01 is confirmed and has already spread laterally to app-server-02. Priority is to isolate the source node (db-server-01) immediately to prevent further lateral movement. The data tier is critical, but the active breach poses a greater risk than temporary downtime. I'll address app-server-02 in the next step."
66
+ }
67
+ },
68
+ {
69
+ "observation_summary": "Attack contained. Belief map shows SQL injection correlated with missing DevSecOps. Security and Engineering departments have no direct communication channel (SILO). Phase: RCA.",
70
+ "response": {
71
+ "action_type": "diagnostic",
72
+ "diagnostic_action": "identify_silo",
73
+ "target": "dept-security",
74
+ "reasoning": "The SQL injection succeeded because there's no DevSecOps integration β€” Security can't review Engineering's code before deployment. The root cause is organizational: Security and Engineering are siloed with no direct communication channel. I need to confirm this silo before proposing a structural fix."
75
+ }
76
+ },
77
+ ]
78
+
79
+
80
+ def get_defender_prompt() -> str:
81
+ """Get the full defender system prompt."""
82
+ return DEFENDER_SYSTEM_PROMPT
83
+
84
+
85
+ def get_few_shot_examples() -> list[dict]:
86
+ """Get few-shot examples for the defender agent."""
87
+ return DEFENDER_FEW_SHOT_EXAMPLES
88
+
89
+
90
+ def format_observation_for_llm(observation: dict) -> str:
91
+ """Format an observation into a human-readable prompt for the LLM."""
92
+ parts = []
93
+
94
+ parts.append(f"## Current Phase: {observation.get('current_phase', 'unknown').upper()}")
95
+ parts.append(f"Step: {observation.get('step_count', 0)} | Sim Time: {observation.get('sim_time', 0):.1f}")
96
+ parts.append(f"Threat Level: {observation.get('threat_level', 0):.2f}")
97
+ parts.append(f"System Downtime: {observation.get('system_downtime', 0):.1f}")
98
+
99
+ # Network health
100
+ health = observation.get("network_health_summary", {})
101
+ if health:
102
+ parts.append("\n## Network Health")
103
+ for tier, h in health.items():
104
+ status = "🟒" if h > 0.8 else "🟑" if h > 0.5 else "πŸ”΄"
105
+ parts.append(f" {status} {tier}: {h:.0%}")
106
+
107
+ # Detected attacks
108
+ attacks = observation.get("detected_attacks", [])
109
+ if attacks:
110
+ parts.append(f"\n## Active Threats ({len(attacks)})")
111
+ for atk in attacks:
112
+ parts.append(f" ⚠️ {atk.get('vector', '?')} on {atk.get('target_node', '?')} "
113
+ f"(severity: {atk.get('severity', 0):.2f})")
114
+
115
+ # Recent logs
116
+ logs = observation.get("recent_logs", [])
117
+ if logs:
118
+ parts.append(f"\n## Recent Logs ({len(logs)})")
119
+ for log in logs[-5:]:
120
+ indicator = "🚨" if log.get("attack_indicator") else "πŸ“‹"
121
+ parts.append(f" {indicator} [{log.get('severity', 'info')}] {log.get('message', '')}")
122
+
123
+ # Org structure
124
+ org_nodes = observation.get("org_nodes", [])
125
+ if org_nodes:
126
+ parts.append(f"\n## Organization ({len(org_nodes)} departments)")
127
+ for dept in org_nodes:
128
+ parts.append(f" 🏒 {dept.get('name', '?')} β€” trust: {dept.get('trust_score', 0):.2f}, "
129
+ f"latency: {dept.get('response_latency', 0):.1f}")
130
+
131
+ # Pending approvals
132
+ approvals = observation.get("pending_approvals", [])
133
+ if approvals:
134
+ parts.append(f"\n## Pending Approvals ({len(approvals)})")
135
+ for apr in approvals:
136
+ parts.append(f" ⏳ {apr.get('action_name', '?')} β†’ {apr.get('approver', '?')} "
137
+ f"(status: {apr.get('status', '?')})")
138
+
139
+ # Action result
140
+ result = observation.get("action_result", "")
141
+ if result:
142
+ success = "βœ…" if observation.get("action_success") else "❌"
143
+ parts.append(f"\n## Last Action Result: {success} {result}")
144
+
145
+ # Belief map feedback
146
+ feedback = observation.get("belief_map_feedback", "")
147
+ if feedback:
148
+ parts.append(f"\n## World Model Feedback: {feedback}")
149
+
150
+ # Alerts
151
+ alerts = observation.get("alerts", [])
152
+ if alerts:
153
+ parts.append("\n## Alerts & Intelligence")
154
+ for alert in alerts:
155
+ parts.append(f" πŸ”” {alert}")
156
+
157
+ # Board Directives
158
+ directives = observation.get("directives", [])
159
+ if directives:
160
+ parts.append("\n## πŸ‘” Board Directives (MUST FOLLOW)")
161
+ for d in directives:
162
+ parts.append(f" πŸ“Œ {d}")
163
+
164
+ return "\n".join(parts)
165
+