T09 · Insecure Skill Coding Practices
- Location
wrappers/paired-sms-command-hook.py:294- Finding
Legacy session-log dispatcher trusts forgeable sender metadata and can execute unauthorized phone actions
- Content
View full analysis
Vulnerability Details
File Location:
wrappers/paired-sms-command-hook.py, lines 294–303, 339–357, 700–713, and 745–763
Vulnerability Type: Authentication bypass through untrusted session content
Risk Level: MediumVulnerable Code Snippets
The legacy parser extracts the purported sender identity directly from message text:
python mid_match = re.search(r'"message_id":\s*"?(\d+)"?', full_text) sender_match = re.search(r'"sender_id":\s*"?(\d+)"?', full_text) base = { "session_event_id": e.get("id"), "session_event_ts": e.get("timestamp"), "telegram_message_id": int(mid_match.group(1)) if mid_match else None, "sender_id": sender_match.group(1) if sender_match else None, }The same text-derived identity is then treated as an authorization check before executing the SMS sender:
python if not ALLOWED_SENDER_ID or parsed.get("sender_id") != ALLOWED_SENDER_ID: log.warning( f"REJECTED /sms from sender_id={parsed.get('sender_id')} " f"(only {ALLOWED_SENDER_ID} is allowed)") record["result"] = {"ok": False, "error": "sender_not_allowed"} append_dispatch_log(record) return record log.info(f"DISPATCH /sms: number={parsed['number']} body={parsed['body'][:60]!r}") try: p = subprocess.run( [SMS_SEND_BIN, parsed["number"], parsed["body"], "--json", "--auto-unlock", "--relock"], capture_output=True, text=True, timeout=45, )New session-log entries are parsed and dispatched as commands:
python parsed = parse_message_line(line) if parsed is None: continue eid = parsed.get("session_event_id") if eid and eid in seen_event_ids: continue if eid: seen_event_ids.add(eid) cmd_type = parsed.get("command", "sms") log.info(f"Found /{cmd_type} event: msg_id={parsed.get('telegram_message_id')}") if cmd_type == "sms": dispatch_sms(parsed, token, chat_id) elif cmd_type in ("phone_dial", "phone_verb", "phone_say", "phone_attach"): dispatch_phone(parsed, token ...[truncated 3956 chars]- Remediation
View remediation
Remediation Suggestions
- Remove
paired-sms-command-hook.pyfrom the distributed package, or permanently disable its session-log dispatch functionality. - Do not treat identifiers parsed from message bodies as authenticated sender metadata.
- Route every actionable command through the HMAC-signed inbox implemented by
paired-inbox-hook.py. - If backward compatibility is unavoidable:
- Require an HMAC signature over the complete command payload.
- Validate a short timestamp window and unique nonce.
- Bind the destination, message body, action, and confirmation state into the signed payload.
- Enforce trusted-number checks immediately before every SMS or call.
- Do not permit session JSONL, chat memory, SMS bodies, notification text, or web content to act directly as a command source.
- Avoid passing
--auto-unlockfrom any compatibility dispatcher unless the signed command explicitly authorizes unlocking. - Add regression tests proving that forged
"sender_id"text cannot authorize commands and that unsigned external content never reaches phone-action subprocesses. - Update installation and migration instructions to remove any legacy services and direct users exclusively to
paired-inbox-hook.service.
- Remove
