Skip to content

fix: Prevent SSRF in import and app package URL fetches#40338

Open
aditya-c7 wants to merge 2 commits intoRocketChat:developfrom
aditya-c7:security-harden-import-and-app-url-fetch
Open

fix: Prevent SSRF in import and app package URL fetches#40338
aditya-c7 wants to merge 2 commits intoRocketChat:developfrom
aditya-c7:security-harden-import-and-app-url-fetch

Conversation

@aditya-c7
Copy link
Copy Markdown

@aditya-c7 aditya-c7 commented Apr 30, 2026

Summary

This PR hardens two server-side URL fetch paths that can be security-sensitive in self-hosted deployments:

  • Routes public import downloads through @rocket.chat/server-fetch with SSRF validation enabled and the configured SSRF_Allowlist applied.
  • Removes support for user-controlled local filesystem paths in downloadPublicImportFile.
  • Keeps private app package URL installation/update support, but no longer bypasses SSRF validation for caller-supplied URLs.

Security impact

The previous importer flow accepted both remote URLs and local filesystem paths from a user with run-import, then used raw http/https or fs.createReadStream. That could allow a privileged importer account to make the Rocket.Chat server reach internal network resources or read local files into the import pipeline.

The apps management flow also explicitly bypassed SSRF validation for caller-provided app package URLs. Even though this path is gated by manage-apps, keeping Rocket.Chat's SSRF protections active for user-controlled destinations reduces blast radius if a privileged session or delegated role is compromised. Intentional exceptions can still use the configured SSRF_Allowlist.

Testing

  • Rebased on official RocketChat/Rocket.Chat develop.
  • Ran git diff --check successfully.
  • Did not run the full test suite locally because dependencies are not installed in this sparse checkout.

Areas touched

  • Importer public file download flow.
  • Apps private package install/update URL fetch flow.

Copilot AI review requested due to automatic review settings April 30, 2026 09:56
@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot Bot commented Apr 30, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 30, 2026

⚠️ No Changeset found

Latest commit: 6ec235b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Walkthrough

Updates the import file download mechanism to enforce SSRF (Server-Side Request Forgery) validation using an allowlist, and removes SSRF validation bypasses from app-related REST endpoints. The importer now strictly handles HTTP(S) URLs with server fetch and buffers responses, removing local filesystem path support.

Changes

Cohort / File(s) Summary
Importer download security hardening
apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts
Refactors URL handling to enforce HTTP(S)-only via getPublicImportUrl helper; replaces direct filesystem path support with serverFetch using SSRF allowlist; switches response handling to buffer content before streaming; enhances error handling with stream destruction and progress updates.
REST endpoint SSRF enforcement
apps/meteor/ee/server/apps/communication/rest.ts
Removes SSRF validation bypasses in app installation and update endpoints by setting ignoreSsrfValidation: false and enforcing allowlist via settings.get('SSRF_Allowlist'); removes associated bypass comments.

Sequence Diagram

sequenceDiagram
    participant Client
    participant ImportMethod as Download Method
    participant Validator as URL Validator
    participant ServerFetch as Server Fetch
    participant Allowlist as SSRF Allowlist
    participant Stream as Import Stream
    
    Client->>ImportMethod: Request file download
    ImportMethod->>Validator: Parse/validate fileUrl
    Validator->>ImportMethod: Validated HTTP(S) URL
    ImportMethod->>Allowlist: Check allowed domain
    Allowlist->>ServerFetch: Domain allowed
    ServerFetch->>ServerFetch: Fetch remote content
    ServerFetch->>ImportMethod: Response (arrayBuffer)
    ImportMethod->>ImportMethod: Buffer to memory
    ImportMethod->>Stream: Write buffered content
    Stream->>Stream: Emit finish event
    Stream->>Client: Import complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

type: bug

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'fix: Prevent SSRF in import and app package URL fetches' accurately and specifically describes the main changes: fixing SSRF vulnerabilities in import file downloads and app package URL handling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@aditya-c7 aditya-c7 changed the title Harden importer and app URL fetches against SSRF fix: Harden importer and app URL fetches against SSRF Apr 30, 2026
@aditya-c7 aditya-c7 changed the title fix: Harden importer and app URL fetches against SSRF fix: Prevent SSRF in import and app package URL fetches Apr 30, 2026
Copy link
Copy Markdown

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

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: 9d7f35384b

ℹ️ 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".

throw new Meteor.Error('error-import-file-download-failed', 'Failed to download import file.', 'downloadPublicImportFile');
}

const fileBuffer = Buffer.from(await response.arrayBuffer());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Stream import downloads instead of buffering whole file

This now reads the full remote import file into memory (response.arrayBuffer() then Buffer.from(...)) before writing it to storage, which is a regression from the previous streaming behavior and can exhaust Node heap on large imports. In production, a sufficiently large CSV/JSON export can cause high memory spikes or process crashes during downloadPublicImportFile, interrupting imports for all users. Keep the SSRF validation, but write from the response stream to writeStream to preserve bounded memory usage.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Hardens two server-side URL fetch flows to reduce SSRF and local file read risk in self-hosted deployments by enforcing @rocket.chat/server-fetch SSRF protections and applying the configured SSRF_Allowlist.

Changes:

  • Enforce SSRF validation (and apply SSRF_Allowlist) when installing/updating private apps from a caller-supplied URL.
  • Restrict downloadPublicImportFile to HTTP/HTTPS URLs only (no local filesystem paths) and route downloads through @rocket.chat/server-fetch with SSRF validation enabled.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
apps/meteor/ee/server/apps/communication/rest.ts Enforces SSRF validation + allowlist for user-supplied app package URLs in Apps REST endpoints.
apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts Removes local-path import downloads; validates URL scheme and fetches via server-fetch with SSRF allowlist.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +36 to +40
const fileBuffer = Buffer.from(await response.arrayBuffer());
await new Promise<void>((resolve, reject) => {
writeStream.once('error', reject);
writeStream.end(fileBuffer, resolve);
});
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

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

downloadHttpFile loads the full response into memory (response.arrayBuffer() -> Buffer.from(...)) before writing. Import archives can be large, so this risks high memory usage/OOM and makes the server susceptible to large-download DoS. Prefer streaming the response body into the write stream (with backpressure) and enforce a max size (e.g., Content-Length / configured limit) and/or an explicit download timeout.

Copilot uses AI. Check for mistakes.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 30, 2026

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants