From 30301a12b59f7dde4034253e57bcb53ebae67449 Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar Date: Wed, 11 Mar 2026 21:48:54 +0100 Subject: [PATCH] fix: pentest session ID propagation, target name resolution, BSON field paths - Set session.id from insert_one result so orchestrator has the ID - Enrich sessions with target_name by joining DAST targets in server fns - Fix _id.$oid BSON field path for target dropdown and session list - Fix send_message URL to /chat (was /messages) Co-Authored-By: Claude Opus 4.6 --- compliance-agent/src/api/handlers/pentest.rs | 5 +- .../src/infrastructure/pentest.rs | 65 ++++++++++++++++++- .../src/pages/pentest_dashboard.rs | 13 +++- 3 files changed, 76 insertions(+), 7 deletions(-) diff --git a/compliance-agent/src/api/handlers/pentest.rs b/compliance-agent/src/api/handlers/pentest.rs index ea25c09..4675db7 100644 --- a/compliance-agent/src/api/handlers/pentest.rs +++ b/compliance-agent/src/api/handlers/pentest.rs @@ -76,7 +76,7 @@ pub async fn create_session( let mut session = PentestSession::new(req.target_id.clone(), strategy); session.repo_id = target.repo_id.clone(); - agent + let insert_result = agent .db .pentest_sessions() .insert_one(&session) @@ -88,6 +88,9 @@ pub async fn create_session( ) })?; + // Set the generated ID back on the session so the orchestrator has it + session.id = insert_result.inserted_id.as_object_id(); + let initial_message = req.message.unwrap_or_else(|| { format!( "Begin a {} penetration test against {} ({}). \ diff --git a/compliance-dashboard/src/infrastructure/pentest.rs b/compliance-dashboard/src/infrastructure/pentest.rs index 3dd5436..4fd8a72 100644 --- a/compliance-dashboard/src/infrastructure/pentest.rs +++ b/compliance-dashboard/src/infrastructure/pentest.rs @@ -34,14 +34,50 @@ pub struct AttackChainResponse { pub async fn fetch_pentest_sessions() -> Result { let state: super::server_state::ServerState = dioxus_fullstack::FullstackContext::extract().await?; + + // Fetch sessions let url = format!("{}/api/v1/pentest/sessions", state.agent_api_url); let resp = reqwest::get(&url) .await .map_err(|e| ServerFnError::new(e.to_string()))?; - let body: PentestSessionsResponse = resp + let mut body: PentestSessionsResponse = resp .json() .await .map_err(|e| ServerFnError::new(e.to_string()))?; + + // Fetch DAST targets to resolve target names + let targets_url = format!("{}/api/v1/dast/targets", state.agent_api_url); + if let Ok(tresp) = reqwest::get(&targets_url).await { + if let Ok(tbody) = tresp.json::().await { + let targets = tbody.get("data").and_then(|v| v.as_array()); + if let Some(targets) = targets { + // Build target_id -> name lookup + let target_map: std::collections::HashMap = targets + .iter() + .filter_map(|t| { + let id = t.get("_id")?.get("$oid")?.as_str()?.to_string(); + let name = t.get("name")?.as_str()?.to_string(); + Some((id, name)) + }) + .collect(); + + // Enrich sessions with target_name + for session in body.data.iter_mut() { + if let Some(tid) = session.get("target_id").and_then(|v| v.as_str()) { + if let Some(name) = target_map.get(tid) { + session.as_object_mut().map(|obj| { + obj.insert( + "target_name".to_string(), + serde_json::Value::String(name.clone()), + ) + }); + } + } + } + } + } + } + Ok(body) } @@ -53,10 +89,33 @@ pub async fn fetch_pentest_session(id: String) -> Result().await { + if let Some(targets) = tbody.get("data").and_then(|v| v.as_array()) { + for t in targets { + let t_id = t.get("_id").and_then(|v| v.get("$oid")).and_then(|v| v.as_str()).unwrap_or(""); + if t_id == tid { + if let Some(name) = t.get("name").and_then(|v| v.as_str()) { + body.data.as_object_mut().map(|obj| { + obj.insert("target_name".to_string(), serde_json::Value::String(name.to_string())) + }); + } + break; + } + } + } + } + } + } + Ok(body) } @@ -150,7 +209,7 @@ pub async fn send_pentest_message( let state: super::server_state::ServerState = dioxus_fullstack::FullstackContext::extract().await?; let url = format!( - "{}/api/v1/pentest/sessions/{session_id}/messages", + "{}/api/v1/pentest/sessions/{session_id}/chat", state.agent_api_url ); let client = reqwest::Client::new(); diff --git a/compliance-dashboard/src/pages/pentest_dashboard.rs b/compliance-dashboard/src/pages/pentest_dashboard.rs index 647f581..0159f4c 100644 --- a/compliance-dashboard/src/pages/pentest_dashboard.rs +++ b/compliance-dashboard/src/pages/pentest_dashboard.rs @@ -34,7 +34,8 @@ pub fn PentestDashboardPage() -> Element { Ok(resp) => { let session_id = resp .data - .get("id") + .get("_id") + .and_then(|v| v.get("$oid")) .and_then(|v| v.as_str()) .unwrap_or("") .to_string(); @@ -241,7 +242,10 @@ pub fn PentestDashboardPage() -> Element { div { style: "display: grid; gap: 12px; padding: 16px;", for session in sess_list { { - let id = session.get("id").and_then(|v| v.as_str()).unwrap_or("-").to_string(); + let id = session.get("_id") + .and_then(|v| v.get("$oid")) + .and_then(|v| v.as_str()) + .unwrap_or("-").to_string(); let target_name = session.get("target_name").and_then(|v| v.as_str()).unwrap_or("Unknown Target").to_string(); let status = session.get("status").and_then(|v| v.as_str()).unwrap_or("unknown").to_string(); let strategy = session.get("strategy").and_then(|v| v.as_str()).unwrap_or("-").to_string(); @@ -329,7 +333,10 @@ pub fn PentestDashboardPage() -> Element { rsx! { for target in &data.data { { - let tid = target.get("id").and_then(|v| v.as_str()).unwrap_or("").to_string(); + let tid = target.get("_id") + .and_then(|v| v.get("$oid")) + .and_then(|v| v.as_str()) + .unwrap_or("").to_string(); let tname = target.get("name").and_then(|v| v.as_str()).unwrap_or("Unknown").to_string(); let turl = target.get("base_url").and_then(|v| v.as_str()).unwrap_or("").to_string(); rsx! {