feat: align task pipe protocol and hmac

This commit is contained in:
zyl
2026-03-25 03:25:47 +00:00
parent 8757bbb266
commit b9773d4719
5 changed files with 168 additions and 8 deletions

View File

@@ -97,6 +97,11 @@ impl<T: Transport> BrowserPipeTool<T> {
"received duplicate init after handshake".to_string(),
));
}
BrowserMessage::SubmitTask { .. } => {
return Err(PipeError::UnexpectedMessage(
"received submit_task while waiting for response".to_string(),
));
}
}
}
}

View File

@@ -12,6 +12,9 @@ pub enum BrowserMessage {
#[serde(default)]
capabilities: Vec<String>,
},
SubmitTask {
instruction: String,
},
Response {
seq: u64,
success: bool,
@@ -31,6 +34,14 @@ pub enum AgentMessage {
agent_id: String,
supported_actions: Vec<Action>,
},
LogEntry {
level: String,
message: String,
},
TaskComplete {
success: bool,
summary: String,
},
Command {
seq: u64,
action: Action,

View File

@@ -1,6 +1,7 @@
use hmac::{Hmac, Mac};
use serde_json::Value;
use sha2::{Digest, Sha256};
use std::fmt::Write as _;
use crate::pipe::Action;
use crate::security::SecurityError;
@@ -36,13 +37,53 @@ pub fn sign_command(
let mut mac = HmacSha256::new_from_slice(session_key)
.map_err(|err| SecurityError::Hmac(err.to_string()))?;
mac.update(seq.to_string().as_bytes());
mac.update(b"|");
mac.update(action.as_str().as_bytes());
mac.update(b"|");
mac.update(expected_domain.as_bytes());
mac.update(b"|");
mac.update(serde_json::to_string(params)?.as_bytes());
let canonical = format!(
"{}\n{}\n{}\n{}",
seq,
action.as_str(),
stable_json_string(params)?,
expected_domain
);
mac.update(canonical.as_bytes());
Ok(hex::encode(mac.finalize().into_bytes()))
}
fn stable_json_string(value: &Value) -> Result<String, SecurityError> {
match value {
Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) => {
serde_json::to_string(value).map_err(SecurityError::from)
}
Value::Array(items) => {
let mut out = String::from("[");
for (index, item) in items.iter().enumerate() {
if index > 0 {
out.push(',');
}
out.push_str(&stable_json_string(item)?);
}
out.push(']');
Ok(out)
}
Value::Object(map) => {
let mut keys: Vec<&str> = map.keys().map(String::as_str).collect();
keys.sort_unstable();
let mut out = String::from("{");
for (index, key) in keys.iter().enumerate() {
if index > 0 {
out.push(',');
}
write!(
out,
"{}:{}",
serde_json::to_string(key)?,
stable_json_string(&map[*key])?
)
.map_err(|err| SecurityError::Hmac(err.to_string()))?;
}
out.push('}');
Ok(out)
}
}
}