Repository navigation
fix: authenticate image attachment preview urls to prevent 403 errors - #1403
swarnendusahu10-dotcom wants to merge 2 commits into
Conversation
|
Hi @Aryan-Verma-999, gentle bump on this one. All CI checks are green with 0 merge conflicts against latest develop. Could you please let me know if this looks good to merge or if there's anything you'd like me to update. Appreciate your guidance! ✨ |
|
hey @swarnendusahu10-dotcom, appending |
…m without exposing credentials in URLs
|
Hi @Aryan-Verma-999! 👋 Great point on token exposure. I’ve refactored this in commit e194923 to use a credential-preserving blob delivery mechanism:
Formatted with prettier@2.8.1 and Rollup build verified clean. Ready for your review! 🙌 |
|
Can you share a demo video, demonstrating that you're not getting the 403 |
|
@Aryan-Verma-999 I will give u the video , but i need some time before that , i Have my final exams from tmrw . Sry for the delay . But it will run for like a week , if i get time in btw i will give u the vid or nxt week i will give u a proper demo . |
No worries, take your time :) |
Summary
Fixes #1229
When Rocket.Chat servers have the default "Block Unauthenticated Access" setting enabled for uploaded files under
/file-upload/..., image attachment previews rendered directly via HTML<img>tags fail to load with403 Forbiddenbecause standard browser image requests do not carry custom HTTP headers (X-Auth-Token/X-User-Id).This pull request introduces an authenticated media URL handler that appends Rocket.Chat's query-parameter authentication (
?rc_token=<token>&rc_uid=<userId>) to internal file upload URLs while strictly safeguarding external URLs against credential leakage.Security Architecture & Validation Boundary
To guarantee that user authentication credentials (
rc_token,rc_uid) can never leak to third-party domains or external image hosts (CWE-200 prevention), URL resolution enforces a strict dual-boundary validation:flowchart TD A["Incoming Media URL<br/><i>(attachment.image_url)</i>"] --> B{"Is URL falsy or empty?"} B -- "Yes" --> C["Return '' (Defensive Guard)"] B -- "No" --> D{"Is URL Relative or Absolute?"} D -- "Relative (/file-upload/...)" --> E{"Path starts with<br/>'/file-upload/'?"} D -- "Absolute (http/https)" --> F{"Origin === Rocket.Chat Host Origin?"} F -- "No (External / Attacker URL)" --> G["Return Raw External URL<br/><b>[ZERO TOKEN LEAKAGE - CWE-200 SAFE]</b>"] F -- "Yes (Same Origin)" --> E E -- "No (e.g. /avatar/)" --> H["Return host + path URL without tokens"] E -- "Yes (/file-upload/)" --> I{"Are rc_token & rc_uid available?"} I -- "No (Unauthenticated / Anonymous)" --> H I -- "Yes (Authenticated Session)" --> J["Append ?rc_token=...&rc_uid=... via URLSearchParams<br/><b>[PREVIEW AUTHENTICATED - 403 RESOLVED]</b>"] style A fill:#1f2937,stroke:#4b5563,stroke-width:2px,color:#f3f4f6 style B fill:#374151,stroke:#6b7280,stroke-width:2px,color:#f3f4f6 style C fill:#4b5563,stroke:#9ca3af,stroke-width:1px,color:#f3f4f6 style D fill:#374151,stroke:#6b7280,stroke-width:2px,color:#f3f4f6 style E fill:#1e3a8a,stroke:#3b82f6,stroke-width:2px,color:#eff6ff style F fill:#831843,stroke:#ec4899,stroke-width:2px,color:#fdf2f8 style G fill:#991b1b,stroke:#ef4444,stroke-width:2px,color:#fef2f2 style H fill:#374151,stroke:#9ca3af,stroke-width:1px,color:#f3f4f6 style I fill:#1e3a8a,stroke:#3b82f6,stroke-width:2px,color:#eff6ff style J fill:#065f46,stroke:#10b981,stroke-width:2px,color:#ecfdf5Key Changes
useAuthenticatedMediaUrlHook (packages/react/src/hooks/useAuthenticatedMediaUrl.js):RCInstance.auth.currentUserto prevent loading flash or broken images.RCInstance.auth.getCurrentUser()and reactiveRCInstance.auth.onAuthChangelistener subscriptions./file-upload/paths receive authentication query parameters.ImageAttachment.js&NestedImageAttachment(packages/react/src/views/AttachmentHandler/ImageAttachment.js):<img>source and theAttachmentMetadatadownload URL (fixing403 Forbiddenon attachment download).NestedImageAttachmentsubcomponent, strictly complying with the Rules of Hooks.extractIdFromUrlagainst null/undefined URLs using optional chaining.PropTypescoverage.Verification & Testing
prettier --check.npm run build(dist/cjsanddist/esmgenerated without errors).