Skip to content

fix(sanitize): strip retrieval-only image metadata before send - #131

Merged
StephenTangCook merged 5 commits into
mainfrom
claude/vigorous-mcclintock-ddd911
Jul 1, 2026
Merged

fix(sanitize): strip retrieval-only image metadata before send#131
StephenTangCook merged 5 commits into
mainfrom
claude/vigorous-mcclintock-ddd911

Conversation

@StephenTangCook

Copy link
Copy Markdown
Contributor

Summary

Strip the image metadata fields Slack returns on message retrieval (image_width, image_height, image_bytes, fallback, is_animated) so blocks loaded from an existing message stay valid on send.

Why

Slack attaches these read-only fields to image blocks/elements when a message is fetched via the API, but rejects them on send. Blocks loaded into the builder from an existing message carried them straight into the outgoing payload, causing send errors.

The fix extends the existing recursive sanitizeValue walker in sanitize-blocks.ts with a DROP_KEYS set. Every outgoing block already funnels through this walker via toSlackBlocks (the same place header level and unsafe URLs are stripped), so the fields are dropped anywhere in the tree regardless of provenance. One choke point, no new pass.

Not scoped to image blocks by type: fallback is a blanket key drop. If legacy attachments (where fallback is valid) are ever supported, scope that key to image blocks.

Test plan

  • pnpm typecheck (via npx tsc, biome/tsc/vitest binaries not installed in this worktree)
  • pnpm lint (via npx biome on changed files)
  • pnpm test (sanitize-blocks: 11 passed, incl. 2 new cases for image blocks and nested context elements)

Note: lefthook pre-commit/pre-push were bypassed with --no-verify because the biome/tsc/vitest binaries are not installed in this worktree; equivalent checks were run via npx and pass.

Slack attaches image_width, image_height, image_bytes, fallback, and
is_animated to image blocks/elements when a message is retrieved via the
API, but rejects those fields on send. Blocks loaded from an existing
message carried them into the outgoing payload. Drop them in the shared
sanitize walker so any round-tripped block stays send-valid, regardless
of provenance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
block-kitchen d56ce81 Commit Preview URL

Branch Preview URL
Jul 01 2026, 06:15 PM

StephenTangCook and others added 4 commits July 1, 2026 11:07
Only drop image_width/height/bytes, fallback, and is_animated from
objects with type: 'image' (both the image block and image element),
rather than any object anywhere in the tree. fallback in particular is
a common field name that is valid on other block types, so a blanket
key drop over-scrubbed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the image-only Set with a Map<type, Set<keys>> so the
retrieval-only field strip extends to other block types by adding an
entry. A Map (not a plain object) keeps type-keyed lookups off the
prototype chain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
replaceAll (load message, open-as-new, JSON-drawer apply) set blocks
into state unchanged, so retrieval-only fields survived in the working
state and JSON drawer until send. Run sanitizeBlocks in replaceAll so
loaded blocks enter already send-valid. Uses sanitizeBlocks (not
toSlackBlocks) to keep builder-only fields like header level editable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@StephenTangCook
StephenTangCook merged commit d9032fe into main Jul 1, 2026
13 checks passed
@StephenTangCook
StephenTangCook deleted the claude/vigorous-mcclintock-ddd911 branch July 1, 2026 18:17
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