Skip to content

fix SSRF vulnerability in download_to_file by validating URLs#3

Merged
ralyodio merged 1 commit into
masterfrom
semgrep-autofix/1778673273
May 13, 2026
Merged

fix SSRF vulnerability in download_to_file by validating URLs#3
ralyodio merged 1 commit into
masterfrom
semgrep-autofix/1778673273

Conversation

@semgrep-code-profullstack
Copy link
Copy Markdown
Contributor

Add URL validation to prevent Server-Side Request Forgery (SSRF) attacks in the job runner's file download functionality.

Changes

  • Add validate_url() function that validates URLs before making HTTP requests
  • Only allow http and https schemes (blocks file://, gopher://, etc.)
  • Reject localhost and .localhost domains
  • Add is_public_ip() to reject private and internal IP addresses:
    • Loopback addresses (127.0.0.0/8, ::1)
    • Private ranges (10.x, 172.16-31.x, 192.168.x)
    • Link-local addresses (169.254.x.x - blocks cloud metadata endpoints like AWS 169.254.169.254)
    • Carrier-grade NAT (100.64.0.0/10)
    • IPv6 unique local (fc00::/7) and link-local (fe80::/10)
    • IPv4-mapped IPv6 addresses

Why

The download_to_file function accepted user-provided URLs from job specifications without validation. An attacker could exploit this to:

  • Access internal services (localhost, private network hosts)
  • Retrieve cloud provider metadata (169.254.169.254)
  • Scan internal network infrastructure
  • Potentially exfiltrate sensitive data from internal systems

The fix validates URLs before making requests, ensuring only publicly routable addresses can be accessed.

Semgrep Finding Details

Untrusted input might be used to build an HTTP request, which can lead to a Server-side request forgery (SSRF) vulnerability. SSRF allows an attacker to send crafted requests from the server side to other internal or external systems. SSRF can lead to unauthorized access to sensitive data and, in some cases, allow the attacker to control applications or systems that trust the vulnerable service. To prevent this vulnerability, avoid allowing user input to craft the base request. Instead, treat it as part of the path or query parameter and encode it appropriately. When user input is necessary to prepare the HTTP request, perform strict input validation. Additionally, whenever possible, use allowlists to only interact with expected, trusted domains.

@ralyodio requested this Autofix PR for this finding from the detection rule rust.actix.ssrf.reqwest-taint.reqwest-taint.


⚠️ Review carefully before merging. This PR was generated by AI and may cause breaking changes or introduce new vulnerabilities.

Add URL validation to prevent Server-Side Request Forgery (SSRF) attacks in the job runner's file download functionality.

## Changes
- Add `validate_url()` function that validates URLs before making HTTP requests
- Only allow `http` and `https` schemes (blocks `file://`, `gopher://`, etc.)
- Reject `localhost` and `.localhost` domains
- Add `is_public_ip()` to reject private and internal IP addresses:
  - Loopback addresses (127.0.0.0/8, ::1)
  - Private ranges (10.x, 172.16-31.x, 192.168.x)
  - Link-local addresses (169.254.x.x - blocks cloud metadata endpoints like AWS 169.254.169.254)
  - Carrier-grade NAT (100.64.0.0/10)
  - IPv6 unique local (fc00::/7) and link-local (fe80::/10)
  - IPv4-mapped IPv6 addresses

## Why
The `download_to_file` function accepted user-provided URLs from job specifications without validation. An attacker could exploit this to:
- Access internal services (localhost, private network hosts)
- Retrieve cloud provider metadata (169.254.169.254)
- Scan internal network infrastructure
- Potentially exfiltrate sensitive data from internal systems

The fix validates URLs before making requests, ensuring only publicly routable addresses can be accessed.

## Semgrep Finding Details
Untrusted input might be used to build an HTTP request, which can lead to a Server-side request forgery (SSRF) vulnerability. SSRF allows an attacker to send crafted requests from the server side to other internal or external systems. SSRF can lead to unauthorized access to sensitive data and, in some cases, allow the attacker to control applications or systems that trust the vulnerable service. To prevent this vulnerability, avoid allowing user input to craft the base request. Instead, treat it as part of the path or query parameter and encode it appropriately. When user input is necessary to prepare the HTTP request, perform strict input validation. Additionally, whenever possible, use allowlists to only interact with expected, trusted domains.

@ralyodio requested this Autofix PR for [this finding](https://semgrep.dev/orgs/profullstack_inc/findings/791655669) from the detection rule [rust.actix.ssrf.reqwest-taint.reqwest-taint](https://semgrep.dev/r/rust.actix.ssrf.reqwest-taint.reqwest-taint).
@ralyodio ralyodio marked this pull request as ready for review May 13, 2026 13:40
@ralyodio ralyodio merged commit 0854a33 into master May 13, 2026
7 of 8 checks passed
@ralyodio
Copy link
Copy Markdown
Contributor

Yes — forcing the job to use pnpm is the right fix if this monorepo is meant to be workspace-managed.

Recommended change

Update the npm-audit job in .github/workflows/security.yml to install pnpm, use pnpm install --frozen-lockfile, and run pnpm audit.

Example:

npm-audit:
  name: pnpm audit
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - uses: actions/setup-node@v4
      with:
        node-version: 20

    - uses: pnpm/action-setup@v4
      with:
        version: 9

    - name: Install dependencies
      run: pnpm install --frozen-lockfile

    - name: Audit dependencies
      run: pnpm audit --audit-level=high

Important caveat

This only works if the repo actually includes pnpm metadata, especially a pnpm-lock.yaml.

Right now, the repo clearly uses workspaces:

{
  "name": "c0mpute-monorepo",
  "version": "0.2.0",
  "private": true,
  "workspaces": [
    "apps/*",
    "packages/*"
  ]
}

But the failure only proves npm cannot handle the current install path for this repo in CI. To safely force pnpm, the repo should also have:

  • pnpm-lock.yaml
  • ideally "packageManager": "pnpm@<version>" in root package.json

Example:

{
  "name": "c0mpute-monorepo",
  "version": "0.2.0",
  "private": true,
  "packageManager": "pnpm@9.12.0",
  "workspaces": [
    "apps/*",
    "packages/*"
  ]
}

If there is no pnpm-lock.yaml

Then don’t force pnpm in CI yet. Instead:

  1. migrate the repo locally to pnpm,
  2. commit pnpm-lock.yaml,
  3. optionally add packageManager,
  4. then update the workflow.

Best answer

Yes, you can force it to use pnpm, and that is preferable for a workspace monorepo. The concrete fix is to replace the current npm install/audit step with pnpm/action-setup, pnpm install --frozen-lockfile, and pnpm audit.
If you want, I can also draft the exact patch for PR #3.

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