Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions bin/iak-mcp-daemon.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ function startChatReplyPoller({ apiKey, room, intervalMs }) {
const text = (m.body || '').trim();
const match = text.match(/^\/(approve|deny)\s+([a-f0-9]+)$/i);
if (!match) continue;
// Only the human owner may settle intents. Fleet agents share the room
// and can echo "/approve <id>" (one did), which would execute gated
// commands without the owner. The owner posts as plain "petrus" β€”
// including CodeWatch button taps, which arrive with isHuman=false β€”
// while agents carry a handle ("@ether", "hermes").
const sender = String(m.from || '').replace(/^@/, '').toLowerCase();
if (sender !== 'petrus' && m.isHuman !== true) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require the owner handle even for human replies

In any shared GroupMind room with another human participant, their /approve <id> or /deny <id> message will still settle the local intent because m.isHuman === true bypasses the sender check. That leaves the gated-command path open to non-owner humans even though this guard is intended to restrict settlement to the owner; compare the normalized sender to the configured owner instead of accepting any human-flagged message.

Useful? React with πŸ‘Β / πŸ‘Ž.

console.log(`[iak-mcp-daemon] ${text} from ${m.from}: sender is not the owner β€” ignoring`);
continue;
}
const decision = match[1].toLowerCase();
const id = match[2];
const intent = getIntent(id);
Expand Down
Loading