Summary
The resolve_permission function accepts a conversation_id parameter but never verifies that the pending approval request_id belongs to that conversation. Any conversation can approve/deny any pending AI tool permission request from any other conversation.
Location
src-tauri/crates/mas-ai/src/service.rs:533-549
pub async fn resolve_permission(
&self,
_conversation_id: &str, // Accepted but never used for verification
request_id: &str,
allowed: bool,
) -> Result<(), AiError> {
let sender = {
let mut approvals = self.pending_approvals.lock().await;
approvals.remove(request_id).ok_or(AiError::NoPendingPermission)?
};
// ...
}
Impact
- User A in conversation tab 1 can approve/deny an AI tool execution request that originated from user/conversation tab 2
- This bypasses the intent of per-conversation permission scoping
- If multiple AI conversations are active simultaneously, permissions are not properly isolated
Fix
Verify that request_id belongs to conversation_id before resolving the permission:
let sender = {
let mut approvals = self.pending_approvals.lock().await;
let approval = approvals.remove(request_id)
.ok_or(AiError::NoPendingPermission)?;
if approval.conversation_id != conversation_id {
return Err(AiError::PermissionConversationMismatch);
}
approval.sender
};
Note: this requires storing conversation_id alongside the sender in the pending_approvals map.
Summary
The
resolve_permissionfunction accepts aconversation_idparameter but never verifies that the pending approvalrequest_idbelongs to that conversation. Any conversation can approve/deny any pending AI tool permission request from any other conversation.Location
src-tauri/crates/mas-ai/src/service.rs:533-549Impact
Fix
Verify that
request_idbelongs toconversation_idbefore resolving the permission:Note: this requires storing
conversation_idalongside the sender in thepending_approvalsmap.