Repository navigation
--wrap-untrusted wraps Gmail header names, so a lookup by name finds nothing #1183
Description
Activity
- addedP2Normal priority bug or improvement with limited blast radius.Normal priority bug or improvement with limited blast radius.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.ClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.ClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.ClawSweeper found a high-confidence source-level issue reproduction.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.This issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.Very strong issue quality with high-confidence source-level or clear reproduction.
on Oct 2, 2026 clawsweeper commented
on Oct 2, 2026 clawsweeperboton Oct 2, 2026 – with ClawSweeperContributorMore actionsCodex review: this still needs some work. Reviewed October 3, 2026, 12:51 AM ET / 04:51 UTC.
Summary
The header-lookup defect remains on current main and v0.43.0. No open fixing PR was found; the repair needs a narrowly defined exemption from the untrusted-content boundary.Reproducibility: yes. the reported wrapped/unwrapped Gmail reads provide a concrete reproduction path, and current source deterministically wraps From in raw header entries. This review inspected source without executing Gmail or tests.
Maintainer decision needed
Question Recommendation Should unwrapped Gmail header identifiers be limited to recognized standard names, or include every syntactically validated custom field name? Preserve recognized identifiers: Start with recognized standard names at the Gmail payload-header boundary and keep custom or malformed names wrapped. Why: The shared formatter treats fetched names as untrusted content; syntax validity alone does not settle which externally chosen identifiers may bypass that protection.
Next step
Confirm the trusted header-identifier boundary before a focused repair with value-wrapping regressions and a credited Unreleased entry.Security
Needs attention: The defect is concrete, but its exemption must preserve the agent-facing untrusted-content boundary.Review details
Best possible solution:
Use a Gmail-specific, validated header-identifier exemption that preserves lookups while retaining value wrapping and protection for unrelated names.
Do we have a high-confidence way to reproduce the issue?
Yes: the reported wrapped/unwrapped Gmail reads provide a concrete reproduction path, and current source deterministically wraps From in raw header entries. This review inspected source without executing Gmail or tests.
Is this the best way to solve the issue?
Unclear: a path-aware exception is the right repair shape, but a parent-key-only exemption is broader than the existing validated metadata pattern.
AGENTS.md: found and applied where relevant.
Remaining risk / open question:
- Exempting every name beneath any headers key could leave unrelated or malformed external text unwrapped; the permitted Gmail identifier boundary must be explicit.
Codex review notes: model internal, reasoning medium; reviewed against 414e2ff8afa2.
Label changes
Label changes:
- add
clawsweeper:needs-security-review: Current issue advisory state selects this label.
Label justifications:
P2: An opt-in output mode breaks established Gmail header selection with a limited blast radius.impact:other: The concrete impact is broken scriptable header lookup, rather than message delivery or authentication.
Evidence reviewed
Security concerns:
- [low] Define the header-name exemption narrowly —
internal/outfmt/untrusted.go:224
The suggested parent-key exception would bypass wrapping for arbitrary fetched names under headers; constrain it to the approved Gmail identifier boundary while preserving value and malformed-name protection.
Confidence: 0.9
What I checked:
- Current source establishes the defect: Array traversal preserves the headers path. The classifier exempts validated Chat resource names, but otherwise classifies both name and value as content, so a raw Gmail header named From cannot survive unchanged. (
internal/outfmt/untrusted.go:219, 414e2ff8afa2) - Both reported command paths are affected: Message JSON includes the original Gmail message and calls WriteJSON. Thread JSON likewise includes the original thread at internal/cmd/gmail_thread.go:90-108. WriteJSON applies the shared wrapper before encoding. (
internal/cmd/gmail_get.go:94, 414e2ff8afa2) - Release and default-branch checks: The main branch API returned the inspected checkout SHA. The v0.43.0 classifier has the same global name/value classification and no Gmail header-name exception. The reporter supplied a macOS wrapped/unwrapped comparison yielding zero versus one From matches; this review did not execute Gmail. (
internal/outfmt/untrusted.go:219, 3b5122f4c81c) - Existing output and safety contracts: Raw API documentation describes marking free text while preserving machine-usable metadata. Formatter tests preserve narrowly validated Chat identifiers while keeping malformed identifiers and display names wrapped. Gmail tests explicitly require instruction-like Reply-To values to remain wrapped. (
internal/outfmt/untrusted_test.go:147, 414e2ff8afa2) - Related merged work does not fix this defect: Wrap fetched content in untrusted output markers #577 established the opt-in wrapping boundary. feat(gmail): expose Reply-To in flattened headers #1057 added flattened Reply-To and retained wrapping of its sender-controlled value; neither provides a raw header-name exemption. (
internal/outfmt/untrusted.go:284, e29e676cefca) - Current implementation ownership context: File history and GitHub commit metadata connect steipete to validated metadata exemptions and hashtag1974 to Reply-To wrapping. GitHub metadata also connects VACInc to the original wrapper feature. Local blame and historical patch inspection encountered unavailable blobs; exact source-line introduction was not established. (
internal/outfmt/untrusted.go, 414e2ff8afa2)
Likely related people:
- steipete: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
- hashtag1974: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
- VACInc: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
How this review workflow works
- ClawSweeper keeps one durable marker-backed review comment per issue or PR.
- Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
- A fresh review can be triggered by eligible
@clawsweeper re-reviewcomments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch. - PR/issue authors and users with repository write access can comment
@clawsweeper re-reviewor@clawsweeper re-runon an open PR or issue to request a fresh review only. - Maintainers can also comment
@clawsweeper reviewto request a fresh review only. - Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
- Maintainer-only repair and merge flows require explicit commands such as
@clawsweeper autofix,@clawsweeper automerge,@clawsweeper fix ci, or@clawsweeper address review. - Maintainers can comment
@clawsweeper explainto ask for more context, or@clawsweeper stopto stop active automation.
- addedclawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.ClawSweeper marked this issue as needing security-sensitive review.
on Oct 3, 2026 Fixed in #1191. Standard ASCII header identifiers now remain usable for name-based selection at Gmail payload-header paths (including nested MIME parts). Custom/malformed names and all raw values remain wrapped; flattened sender and recipient display text is now wrapped too.
The new synthetic regressions failed before the repair for message, thread, draft, and raw output. After the fix, focused formatter tests and the full
make cigate passed on AWS Crabbox (cbx_82fe63e89d13, runrun_d775bb5d1b14177e01af47d72b9f5411). Final independent Codex review found no P0–P2 issues. Exact-head CI passed atba3f9c48194ab95ed337992b443b8b4418c47174, including Linux, minimum Go, macOS, Windows, worker, Docker, and CodeQL: https://github.com/openclaw/gogcli/actions/runs/37571124228Thanks @postoso for identifying both output inconsistencies.
- added a commit that references this issue
on Oct 7, 2026
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
With
--wrap-untrusted, thenameof every raw Gmail header is wrapped in untrusted-content markers along with its value, soselect(.name == "From")matches nothing.Tested with v0.43.0 (
3b5122f4) on macOS:Each wrapped name looks like this:
gmail thread get <tid> --full --jsondoes the same for every header in.thread.messages[].payload.headers[]. Without--wrap-untrustedthe names are plain.The cause looks like the key rule in
internal/outfmt/untrusted.go:nameandvalueare content keys regardless of where they sit, so a header entry{name, value}gets both wrapped. Header names are RFC 5322 field names, not message content.gogcli/internal/outfmt/untrusted.go
Lines 219 to 294 in 414e2ff
Expected: header names stay plain and only values are wrapped, for example by exempting
namewhen the parent path element isheaders.Separately noticed in the flattened
.message.headersobject:subjectandreply_toare wrapped butfromis not, even though the From display name is just as sender-controlled. That may be deliberate. I only checkedgmail getandgmail thread get.