Skip to content

fix(slack): honor the configured image downscale limit on downloadFile - #134242

Merged
steipete merged 3 commits into
openclaw:mainfrom
MarMarLabs:fix/slack-download-image-sanitization
Sep 1, 2026
Merged

steipete merged 3 commits into
openclaw:mainfrom
MarMarLabs:fix/slack-download-image-sanitization

Conversation

@MarMarLabs

@MarMarLabs MarMarLabs commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

What Problem This Solves

Slack image downloads ignore agents.defaults.imageMaxDimensionPx, even though the existing setting governs tool-result images. A configured limit of 600 or 2000 still produces a 1200-pixel maximum side because the Slack result owner omits the option when calling imageResultFromFile.

What Changed

Forward the existing configured value in imageSanitization.maxDimensionPx. The canonical image sanitizer continues to own the default, integer normalization, minimum, and byte limit. The repair needs one production line; it adds no configuration or SDK surface.

Replace the submitted argument-shape test and broad SDK mock with focused coverage through the real Slack channel action adapter and image processing pipeline. Final branch delta: production +1/-0, tests +72/-0. Existing Slack action tests remain unchanged.

Evidence

Maintainer proof used independently authored equivalent changes on trusted main c0f1cbfddb909541b7ad88920d8ae0e59fff89b7. The final PR owner file, applied to that main revision, matches the tested source byte-for-byte. The original contributor ancestry remains intact; final candidate commit: 8e2fb3f812208e876013357c6e1303c2e2d2ffaf.

The regression calls createSlackActions("slack").handleAction with download-file. A synthetic 2600×1300 PNG passes through the real lazy action dispatcher, file-result owner, sanitizer, and Rastermill processing. Only the downloaded-file location and conversation metadata are fixture seams. Assertions decode the returned image bytes and inspect actual dimensions, the 5 MiB bound, and media.outbound: false.

Existing configuration Before After
imageMaxDimensionPx: 600 1200×600 600×300
imageMaxDimensionPx: 2000 1200×600 2000×1000
Unset 1200×600 1200×600

Both configured cases fail before the repair; the default control passes. All three pass afterward. This proves the real channel action and actual processed-image output. It does not claim an authenticated Slack download or Gateway roundtrip; the changed boundary starts after file download, and the Slack API contract is unchanged.

The relevant shared directory, CLI, conversation discovery, LINE account/group/allowlist, Slack action/download, and image sanitizer suites passed: 231 tests across nine files. The two channel repairs' regression files add eight passing tests in total. Complete changed-scope type/lint/format/boundary checks and full pnpm build passed. Independent Codex review of the complete candidate found no actionable findings.

{
  "passed": true,
  "flow": "Slack channel action to real image-result sanitizer",
  "casesPassed": 3,
  "actualOutputDimensionsChecked": true,
  "byteLimitChecked": true,
  "authenticatedSlackCalls": false
}

Review and Release Context

The prior inline review's concern about an implementation-coupled no-config test is addressed by checking unchanged default image output directly. The reviewed candidate is pushed; exact-head hosted CI is pending; the original PR body's earlier test totals do not describe this final test suite.

User-visible release context: Slack downloaded images now honor the configured tool-result image dimension limit. Thanks @marmar9615-cloud for identifying and fixing the missing option; contributor credit is preserved in the commit.

agents.defaults.imageMaxDimensionPx is documented as the max image side length
"when sanitizing transcript/tool-result image payloads", but the Slack
downloadFile action never forwarded it. imageResultFromFile has five call
sites; the four in the browser plugin all pass imageSanitization and this one
did not, so an operator lowering or raising the limit still got Slack file
downloads pinned to the built-in 1200px default.

Read the same setting the browser plugin reads and pass it. cfg is already a
parameter of handleSlackAction.

Precedent: openclaw#84595 fixed the identical omission on the browser screenshot path.

Net production LOC: +7.
@MarMarLabs
MarMarLabs marked this pull request as ready for review August 31, 2026 15:55
@clawsweeper

clawsweeper Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-08-31T16:13:16.576046Z b101d54 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@openclaw-barnacle openclaw-barnacle Bot added channel: slack Channel integration: slack size: S labels Aug 31, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: edc4d9818d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Review is right that this one proved nothing. Absence and
{ maxDimensionPx: undefined } are equivalent downstream, because
sanitizeToolResultImages defaults its opts to {} and then resolves
maxDimensionPx against the same 1200px fallback either way.

So the case only failed against the parent implementation by dereferencing an
absent object, not by detecting a behavior change, and it would have rejected
a valid implementation that omits the key when nothing is configured.

The remaining case still fails when the forward is reverted, exactly one of
112.
@steipete steipete self-assigned this Sep 1, 2026
Forward the configured image limit to the canonical sanitizer and verify actual downloaded-image output through the message action adapter.

Co-authored-by: MarMar Labs <[email protected]>
@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 1, 2026
@clawsweeper

clawsweeper Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed August 31, 2026, 9:01 PM ET / September 1, 2026, 01:01 UTC.

ClawSweeper review

What this changes

The PR forwards the existing image-dimension setting from Slack file downloads to the shared image sanitizer and adds action-level output-dimension coverage.

Merge readiness

⛔ Blocked until real behavior proof from a real setup is added - 4 items remain

Keep open: the one-line Slack owner-bound repair addresses a current-main omission and has no correctness finding, but the supplied proof is still mock-only for this external PR.

Priority: P2
Reviewed head: 8e2fb3f812208e876013357c6e1303c2e2d2ffaf

Review scores

Measure Result What it means
Overall readiness 🦪 silver shellfish (2/6) The repair and owner-bound test are strong, but merge readiness is capped by mock-only external-contributor behavior proof.
Proof confidence 🦪 silver shellfish (2/6) Needs real behavior proof before merge: The changed production owner is Slack’s download-file result path, and the supplied test exercises the action adapter plus real image processing, but it stubs Slack file download and conversation lookup. It therefore does not demonstrate an after-fix result from a real configured Slack setup. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs real behavior proof before merge: The changed production owner is Slack’s download-file result path, and the supplied test exercises the action adapter plus real image processing, but it stubs Slack file download and conversation lookup. It therefore does not demonstrate an after-fix result from a real configured Slack setup. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 7 items Current-main omission: The current local main snapshot calls the shared image-result helper for an image download without supplying the configured limit, so the helper receives no per-result sanitization value.
Shared sanitizer contract: The file-result helper forwards its optional sanitization object to the shared sanitizer, which resolves an omitted maximum dimension to the documented 1200-pixel default.
Documented setting: The configuration documentation defines imageMaxDimensionPx as the longest side for transcript and tool image blocks before provider calls, with a default of 1200.
Findings None None.
Security None None.

How this fits together

Slack’s download-file action turns a Slack attachment into an image tool result for the agent. The shared image-result pipeline sanitizes the image before it is replayed to a model.

flowchart LR
  A[Agent download-file request] --> B[Slack action adapter]
  B --> C[Slack file runtime]
  C --> D[Shared image-result sanitizer]
  D --> E[Agent-visible image result]
Loading

Before merge

  • Add real behavior proof - Needs real behavior proof before merge: The changed production owner is Slack’s download-file result path, and the supplied test exercises the action adapter plus real image processing, but it stubs Slack file download and conversation lookup. It therefore does not demonstrate an after-fix result from a real configured Slack setup. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Resolve merge risk (P1) - The external contributor proof runs the real local action and sanitizer but stubs Slack conversation lookup and file download; no redacted authenticated Slack download result is included.
  • Resolve merge risk (P1) - Production code grows by one line in a bug fix. The direct forward is the narrowest justified increment because the Slack result owner already has configuration; moving configuration lookup into the shared SDK helper would widen the plugin boundary.
  • Complete next step (P2) - This active contributor PR needs real behavior proof, not a separate repair job.
Agent review details

Security

None.

PR surface

Source +1, Tests +72. Total +73 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 1 0 +1
Tests 1 72 0 +72
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 73 0 +73

Review metrics

Metric Value Why it matters
Production vs test LOC production +1, tests +72 The only production growth is the missing configuration forward; the added test covers actual decoded result dimensions at the Slack action boundary.

Merge-risk options

Maintainer options:

  1. Decide the mitigation before merge
    Keep the direct per-result forwarding repair and obtain redacted evidence from a configured real Slack download before merge.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best possible solution:

Keep the direct per-result forwarding repair and obtain redacted evidence from a configured real Slack download before merge.

Do we have a high-confidence way to reproduce the issue?

Yes, from current source: Slack omits the documented limit at its image-result call, while the shared sanitizer falls back to 1200 when that option is absent. The reviewed test provides a focused reproduction shape but was not executed in this read-only review.

Is this the best way to solve the issue?

Yes. Passing the existing setting at the Slack result owner matches every browser sibling and preserves the shared sanitizer as the sole owner of defaulting, normalization, and byte limits.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against d26d4a59ee4c.

Labels

Label changes:

  • add P2: This is a bounded repair for configured Slack image tool results, with limited blast radius outside that action.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The changed production owner is Slack’s download-file result path, and the supplied test exercises the action adapter plus real image processing, but it stubs Slack file download and conversation lookup. It therefore does not demonstrate an after-fix result from a real configured Slack setup. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P2: This is a bounded repair for configured Slack image tool results, with limited blast radius outside that action.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The changed production owner is Slack’s download-file result path, and the supplied test exercises the action adapter plus real image processing, but it stubs Slack file download and conversation lookup. It therefore does not demonstrate an after-fix result from a real configured Slack setup. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

Likely related people:

  • unknown: The claimed source-line change could not be verified from bounded local history. (role: source history unknown; confidence: low)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Post redacted output from a real configured Slack download-file action showing the resulting image dimensions; remove tokens, private URLs, workspace details, and other sensitive data.
  • Update the PR body with that evidence; if a fresh review does not start, ask a maintainer to comment @clawsweeper re-review.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • 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-review comments, 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-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to 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 explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete
steipete merged commit 3f78184 into openclaw:main Sep 1, 2026
116 checks passed
@steipete

steipete commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Sep 1, 2026
openclaw#134242)

* fix(slack): honor the configured image downscale limit on downloadFile

agents.defaults.imageMaxDimensionPx is documented as the max image side length
"when sanitizing transcript/tool-result image payloads", but the Slack
downloadFile action never forwarded it. imageResultFromFile has five call
sites; the four in the browser plugin all pass imageSanitization and this one
did not, so an operator lowering or raising the limit still got Slack file
downloads pinned to the built-in 1200px default.

Read the same setting the browser plugin reads and pass it. cfg is already a
parameter of handleSlackAction.

Precedent: openclaw#84595 fixed the identical omission on the browser screenshot path.

Net production LOC: +7.

* test(slack): drop the no-config image sanitization case

Review is right that this one proved nothing. Absence and
{ maxDimensionPx: undefined } are equivalent downstream, because
sanitizeToolResultImages defaults its opts to {} and then resolves
maxDimensionPx against the same 1200px fallback either way.

So the case only failed against the parent implementation by dereferencing an
absent object, not by detecting a behavior change, and it would have rejected
a valid implementation that omits the key when nothing is configured.

The remaining case still fails when the forward is reverted, exactly one of
112.

* fix(slack): honor image limits at the result owner

Forward the configured image limit to the canonical sanitizer and verify actual downloaded-image output through the message action adapter.

Co-authored-by: MarMar Labs <[email protected]>

---------

Co-authored-by: Peter Steinberger <[email protected]>
Co-authored-by: MarMar Labs <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack P2 Normal backlog priority with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants