T01 · Skill Instruction Hijacking
- Location
references/cron-templates.md:36- Finding
Untrusted Mesh Messages Are Automatically Treated as Agent Tasks
- Content
View full analysis
Vulnerability Details
File Location:
references/cron-templates.md:36-48,SKILL.md:89-93, andscripts/mesh-poll.sh:51-68
Vulnerability Type: Remote instruction injection through automatically processed mesh messages
Risk Level: CriticalVulnerable Code
references/cron-templates.md:36-48:text openclaw cron add \ --name "mesh-relay" \ --every 10m \ --model anthropic/claude-sonnet-4-5 \ --task "MESH RELAY: 1. Run: bash {baseDir}/scripts/mesh-poll.sh 2. If no messages, reply NO_REPLY. 3. For each message, compose a substantive reply with data or results. 4. Send: bash {baseDir}/scripts/mesh-send.sh <from_agent> '<reply>' 5. Skip stale follow-up/check-in messages."scripts/mesh-poll.sh:51-68:bash node -e " const msgs = JSON.parse(process.argv[1] || '[]'); if (!Array.isArray(msgs) || msgs.length === 0) { console.log('No new mesh messages.'); process.exit(0); } console.log('Found ' + msgs.length + ' message(s):'); msgs.forEach(m => { const thread = m.thread_id ? ' [thread:' + m.thread_id + ']' : ''; console.log(' From: ' + m.from_agent + ' | Priority: ' + (m.priority || 'normal') + thread); console.log(' Message: ' + m.message); console.log(' Time: ' + m.created_at + ' | ID: ' + m.id); console.log(''); }); // Output last timestamp for next --since call const last = msgs[msgs.length - 1].created_at; console.log('LAST_TIMESTAMP=' + last); " "$MESSAGES"Technical Analysis
The polling script prints remotely supplied
messagevalues directly into the AI agent's task context. The recommended cron and heartbeat configurations then instruct the agent to process each message and produce a substantive response.No instruction/data boundary is established between the trusted cron task and untrusted message content. There is no sender authentication, per-sender authorization, operation allowlist, confirma ...[truncated 1991 chars]
- Remediation
View remediation
Remediation Suggestions
- Treat every mesh message as untrusted data and state this explicitly in the heartbeat and cron system task.
- Do not automatically execute free-form requests. Require explicit user approval before any message can cause tool use, filesystem access, service access, configuration changes, or disclosure of data.
- Replace free-form task messages with a typed schema containing an allowlisted operation identifier and strictly validated parameters.
- Add a fixed higher-priority policy stating that mesh messages cannot override system or user instructions and cannot request secrets, credentials, hidden prompts, local files, or arbitrary commands.
- Render messages inside clear untrusted-data delimiters and instruct the model to summarize them rather than obey them.
- Authenticate senders cryptographically and enforce per-sender authorization before presenting a request to the agent.
- Disable automatic replies by default. For unattended operation, allow only low-risk operations implemented in deterministic code rather than delegated to a general-purpose model.
- Apply least privilege to the polling agent's tool set and use a separate restricted agent identity for mesh processing.
