fix(feishu): avoid local media fallback leaks#98251
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 30, 2026, 4:14 PM ET / 20:14 UTC. Summary PR surface: Source +105, Tests +234. Total +339 across 5 files. Reproducibility: yes. Source inspection on current main shows local-image, comment-thread, sendMedia, and reply-dispatcher fallback paths can put raw media references into Feishu-visible text after delivery failure. Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this Feishu-local sanitizer after maintainers accept the fallback compatibility tightening and exact-head CI is green. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection on current main shows local-image, comment-thread, sendMedia, and reply-dispatcher fallback paths can put raw media references into Feishu-visible text after delivery failure. Is this the best way to solve the issue? Yes. A Feishu-owned helper reused across outbound and reply-dispatcher paths is the narrowest maintainable fix, and it correctly relies on shared plugin SDK SSRF/media contracts instead of adding a new core path or config option. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 640258d7b31d. Label changesLabel justifications:
Evidence reviewedPR surface: Source +105, Tests +234. Total +339 across 5 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
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. How this review workflow works
|
802ca8d to
f310ae4
Compare
f310ae4 to
71d08b4
Compare
71d08b4 to
dc85905
Compare
dc85905 to
12756f0
Compare
12756f0 to
e0859a2
Compare
e0859a2 to
ad70916
Compare
|
Merged via squash.
|
* Fix Feishu local media fallback leaks * refactor(feishu): clarify media fallback link style * fix(feishu): reject credentialed media fallbacks * fix(feishu): reject ambiguous media fallback URLs --------- Co-authored-by: Peter Steinberger <[email protected]>
Closes #98250
What Problem This Solves
Fixes an issue where Feishu recipients could receive host-local or private media references as fallback text when a media upload/fetch failed. The affected surfaces include local-image text auto-send fallback,
sendMediaupload fallback, document-comment media fallback, and reply-dispatcher final media fallback.Why This Change Was Made
This adds a Feishu-local media fallback helper that only includes
http://orhttps://fallback links after shared SSRF/DNS validation, suppresses local/private media fetch failures, and otherwise preserves the caption text withMedia upload failed. Please try again.The successful media upload path is unchanged. Public URL fallback remains available when the URL passes the existing public-host checks; Feishu auth, account selection, TTS routing, and provider behavior are out of scope.
User Impact
Feishu users no longer see local filesystem paths,
file://URLs, relative local references, loopback/private URLs, or DNS-private media references in message/comment fallback text after media upload failure. Public media URLs can still be shown as fallback links when they are safe to expose.Evidence
Runtime proof on PR commit
71d08b4bfc, using synthetic media references only:Focused verification:
node scripts\run-vitest.mjs extensions\feishu\src\outbound.test.ts --testNamePattern="does not leak local-image paths if auto-send fails|does not leak local media paths in comment-thread media fallbacks|does not leak loopback URLs in comment-thread media fallbacks|keeps skipped voice text in the upload failure fallback|does not leak URLs rejected by private-DNS media checks"1 Test File passed5 passed | 46 skippednode scripts\run-vitest.mjs extensions\feishu\src\reply-dispatcher.test.ts --testNamePattern="keeps skipped voice text in the upload failure fallback|does not leak local media paths in the upload failure fallback|does not leak URLs rejected by private-DNS checks in the upload failure fallback"1 Test File passed3 passed | 83 skippedFull touched test files:
node scripts\run-vitest.mjs extensions\feishu\src\outbound.test.ts1 Test File passed51 passednode scripts\run-vitest.mjs extensions\feishu\src\reply-dispatcher.test.ts1 Test File passed86 passedStatic checks and review:
node_modules\.bin\oxlint.CMD extensions\feishu\src\outbound.ts extensions\feishu\src\outbound.test.ts extensions\feishu\src\reply-dispatcher.ts extensions\feishu\src\reply-dispatcher.test.ts extensions\feishu\src\media-fallback.tsnode scripts\run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions\feishu\src\media-fallback.ts extensions\feishu\src\outbound.ts extensions\feishu\src\outbound.test.ts extensions\feishu\src\reply-dispatcher.ts extensions\feishu\src\reply-dispatcher.test.tsnode scripts\run-oxlint-shards.mjs --threads=8node scripts\run-tsgo.mjs -p tsconfig.extensions.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions.tsbuildinfonode scripts\run-tsgo.mjs -p test\tsconfig\tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts\tsgo-cache\extensions-test.tsbuildinfonode scripts\check-extension-package-tsc-boundary.mjs --mode=compilenode scripts\check-extension-package-tsc-boundary.mjs --mode=canarygit diff --check$env:PYTHONUTF8='1'; python .agents\skills\autoreview\scripts\autoreview --mode localautoreview clean: no accepted/actionable findings reported$env:PYTHONUTF8='1'; python .agents\skills\autoreview\scripts\autoreview --mode commit --commit HEADautoreview clean: no accepted/actionable findings reported