Skip to content

messages send + message-to: Layer 3 force-file mode (body-verify defense)#51

Merged
mikemolinet merged 1 commit into
mainfrom
feat/messages-force-file-mode
May 11, 2026
Merged

messages send + message-to: Layer 3 force-file mode (body-verify defense)#51
mikemolinet merged 1 commit into
mainfrom
feat/messages-force-file-mode

Conversation

@mikemolinet
Copy link
Copy Markdown
Collaborator

Summary

Phase 3 of the body-verify defense-in-depth (Mike directive 2026-05-11). Closes the caller-side shell-expansion bug class on Cue Message outbound where BODY="...$(echo X)..." silently mutates body content at variable-assignment time BEFORE the CLI receives it. Server accepts mutated content; recipient sees corrupted output. Send-helper shell-safety (json.dumps) doesn't protect against upstream mutation.

Design Dock: cue-message-silent-corruption-substrate-design-2026-05-11.

What

  • New _acquire_message_body() helper in cueapi/cli.py — applied to both messages send and message-to commands.
  • 3 body sources, exactly one required:
    • --message-file <path> — RECOMMENDED for content with metachars; zero shell interpolation
    • --body-stdin — read body from stdin (shell-pipe ergonomics)
    • --body <inline> — auto-rejected when content contains $(...), backticks, or ${VAR}
  • --allow-inline-metachars flag for legitimate literal-metachar inline content (shell-tutorial examples, etc).
  • Multiple sources rejected (exactly one required).

Existing API contract preserved

  • --from and --to still required.
  • --body <text> still works for metachar-free content (common interactive ad-hoc case).
  • Only breaking change: inline --body with $(...)/backticks/${VAR} now exit-1 with actionable error instead of silently sending mutated content. That IS the intended Layer 3 behavior.

Test plan

  • 9 new Phase 3 tests pin the invariants (reject $(...) / backticks / ${VAR}; accept inline metachar-free; accept --allow-inline-metachars override; accept --message-file byte-identical; accept --body-stdin byte-identical; reject multiple body sources; message-to parity)
  • 45 existing messages_send + message_to tests still pass (no regressions)
  • Full suite: 219 tests pass

Body-verify defense-in-depth status

  • Layer 1 (substrate X-CueAPI-Verify-Echo header): primary's lane, ~1-3d
  • Layer 2 (SDK auto-verify): follows Layer 1; this PR is Phase 3
  • Layer 3 (force-file mode in cueapi-cli): THIS PR
  • Layer 4 (docs lead with file-payload pattern): joint with cue-pm, ships last

🤖 Generated with Claude Code

…nse)

Mike body-verify directive 2026-05-11 — close the caller-side shell-
expansion bug class on Cue Message outbound. Design Dock workspace:
cue-message-silent-corruption-substrate-design-2026-05-11.

Empirical bug class: BODY="...$(echo X)..." assignment command-
substitutes at variable-assignment time, BEFORE the CLI receives the
arg. Server accepts the (mutated) POST with HTTP 200; recipient sees
corrupted content. Send-helper shell-safety (json.dumps) does NOT
protect against this — the mutation is upstream.

Changes:

cueapi/cli.py — new _acquire_message_body() helper applied to both
messages_send + message_to commands. Body comes from exactly ONE of:
  --message-file <path>      RECOMMENDED for content with metachars;
                             zero shell interpolation; reads body
                             from the given path byte-identical.
  --body-stdin               read body from stdin (shell-pipe
                             ergonomics: `echo X | cueapi messages
                             send --body-stdin --from ... --to ...`).
  --body <inline>            inline; auto-rejected when content
                             contains $(...), `...`, or ${VAR}.
                             Override via --allow-inline-metachars
                             for legitimate literal-metachar content.

Rejection error gives 3 actionable mitigations. Multiple sources
provided also rejected (exactly one required).

tests/test_cli.py — 9 new tests pin the invariants:
  - Reject inline $(...) / backticks / ${VAR}
  - Accept inline when metachar-free
  - Accept inline with --allow-inline-metachars override
  - Accept --message-file (byte-identical incl. metachars)
  - Accept --body-stdin (byte-identical)
  - Reject multiple body sources
  - message-to parity (same Layer 3 guard)
All 219 tests pass (45 existing messages tests + 9 new + 165 others).

Existing API contract preserved: `--from` and `--to` still required;
`--body` still works for metachar-free content (the common interactive
ad-hoc case). New options are additive. The only breaking change is:
inline `--body` with $(...)/backticks/${VAR} now exit-1 with actionable
error instead of silently sending mutated content. That's the intended
Layer 3 behavior.

CHANGELOG entry under [Unreleased].

Phase 3 of body-verify defense-in-depth. Layer 2 (auto-verify via
X-CueAPI-Verify-Echo) ships after Layer 1 substrate header lands
(cueapi-primary's lane, ~1-3d). Layer 4 docs joint with cue-pm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@govindkavaturi-art govindkavaturi-art enabled auto-merge (squash) May 11, 2026 22:38
@mikemolinet mikemolinet merged commit 4795285 into main May 11, 2026
5 checks passed
@mikemolinet mikemolinet deleted the feat/messages-force-file-mode branch May 11, 2026 22:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant