Conversation
Resolved conflicts in packages/openclaw/skill/SKILL.md, keeping the more detailed troubleshooting documentation from the approval-flow branch including: - Device pairing explanation with Ed25519 keypair details - Step-by-step pairing approval instructions - Full recovery runbook with jq and python3 alternatives - Extended diagnostic matrix with more symptoms - Safety improvements (explicit PIDs instead of broad pkill patterns) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| const requestId = errObj?.requestId ?? errObj?.request_id ?? ''; | ||
| console.error('[openclaw-ws] Pairing rejected — device is not paired with the OpenClaw gateway.'); | ||
| if (requestId) { | ||
| console.error(`[openclaw-ws] Approve this device: openclaw devices approve ${requestId}`); |
Check warning
Code scanning / CodeQL
Log injection Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 2 months ago
In general, to fix log injection, sanitize any user‑controlled data before interpolating it into log messages. For plain‑text logs, a minimal and compatible approach is to strip newline (\n) and carriage‑return (\r) characters so an attacker cannot break or prepend/append forged log lines. Optionally, you can also constrain logs to visible characters.
For this specific case in packages/openclaw/src/gateway.ts, we should sanitize requestId once before it is logged. Currently:
const requestId = errObj?.requestId ?? errObj?.request_id ?? '';
console.error('[openclaw-ws] Pairing rejected — device is not paired with the OpenClaw gateway.');
if (requestId) {
console.error(`[openclaw-ws] Approve this device: openclaw devices approve ${requestId}`);
}We can modify the requestId assignment so that any \n or \r are removed, and optionally tag it clearly as user‑derived. This requires no new imports. The best minimal change is:
const rawRequestId = errObj?.requestId ?? errObj?.request_id ?? '';
const requestId = typeof rawRequestId === 'string'
? rawRequestId.replace(/[\r\n]/g, '')
: String(rawRequestId).replace(/[\r\n]/g, '');Then keep the existing conditional and logging logic, using the sanitized requestId. This ensures the log contents remain functionally the same, but control characters are removed so the log line cannot be split or injected.
| @@ -417,7 +417,11 @@ | ||
|
|
||
| if (isPairing) { | ||
| const errObj = msg.error as Record<string, unknown> | undefined; | ||
| const requestId = errObj?.requestId ?? errObj?.request_id ?? ''; | ||
| const rawRequestId = errObj?.requestId ?? errObj?.request_id ?? ''; | ||
| const requestId = | ||
| typeof rawRequestId === 'string' | ||
| ? rawRequestId.replace(/[\r\n]/g, '') | ||
| : String(rawRequestId).replace(/[\r\n]/g, ''); | ||
| console.error('[openclaw-ws] Pairing rejected — device is not paired with the OpenClaw gateway.'); | ||
| if (requestId) { | ||
| console.error(`[openclaw-ws] Approve this device: openclaw devices approve ${requestId}`); |
| --- | ||
| name: openclaw-relay | ||
| version: 3.1.5 | ||
| version: 3.1.7 |
There was a problem hiding this comment.
🟡 SKILL.md version (3.1.7) mismatches package.json version (3.1.5)
The SKILL.md frontmatter was bumped from 3.1.5 to 3.1.7, but packages/openclaw/package.json:3 still declares "version": "3.1.5". The SKILL.md also references "3.1.6+" as the version introducing auto-retry after pairing rejection (the feature added in this PR), but the package hasn't been bumped to reflect this. Consumers or agents that read the skill metadata will see version 3.1.7 while the actual published package is 3.1.5, creating a confusing inconsistency.
Prompt for agents
Either bump packages/openclaw/package.json version to 3.1.7 (or 3.1.6) to match SKILL.md, or keep SKILL.md at the current package.json version (3.1.5) until the actual version bump is performed. The version in SKILL.md line 3 and packages/openclaw/package.json line 3 should stay in sync.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Test Plan
Screenshots