DoS via GraphQL Blob type not using Workhorse

⚠️ Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #3026555 by pwnie on 2025-03-08, assigned to @gandrews7:

Report | How To Reproduce

Report

Summary
An unprotected GraphQL endpoint in GitLab allows direct access to large repository blobs (via the plainData field), bypassing normal Workhorse/Gitaly timeouts. By repeatedly fetching multiple large files, an attacker can trigger excessive resource consumption, leading to a denial-of-service.

Steps to Reproduce

  1. Upload large files
    • Commit three ~300MB files of random (e.g., Base64) data to your GitLab repository (not via LFS).
  2. Construct GraphQL query
    • Fetch these large files using the plainData field:
      curl 'http://<HOSTNAME>/api/graphql' \  
        -H 'Content-Type: application/json' \  
        --data-raw '{  
          "variables": {},  
          "query": "query {  
            project(fullPath: \"<PROJECT_PATH>\") {  
              repository {  
                blobs(paths: [\"<LARGE_FILE1>\", \"<LARGE_FILE2>\", \"<LARGE_FILE3>\"], ref: \"main\") {  
                  nodes {  
                    path  
                    webPath  
                    plainData  
                  }  
                }  
              }  
            }  
          }"  
        }'  
    • Replace <HOSTNAME>, <PROJECT_PATH>, and filenames accordingly.
  3. Send repeated requests
    • Loop the above request multiple times (possibly in parallel) to simulate an attack.
  4. Observe resource usage
    • Monitor server metrics; repeated queries for large blobs quickly spike memory/CPU usage, potentially causing crashes or severe degradation.

Impact

  • Denial-of-Service (DoS): Flooding the GraphQL endpoint with requests to large blobs consumes excessive resources, making the GitLab instance unresponsive or severely degraded.
  • Minimal Access Requirements: Only knowledge of the target project path and blob paths is required; no special permissions are needed.

Components Affected

  • The GitLab GraphQL API endpoint that returns large blob content (plainData) directly via Rails, bypassing Workhorse and Gitaly timeout protections.

Impact

  • Denial-of-Service (DoS): Flooding the GraphQL endpoint with requests to large blobs consumes excessive resources, making the GitLab instance unresponsive or severely degraded.
  • Minimal Access Requirements: Only knowledge of the target project path and blob paths is required; no special permissions are needed.

Impact

  • Denial-of-Service (DoS): Flooding the GraphQL endpoint with requests to large blobs consumes excessive resources, making the GitLab instance unresponsive or severely degraded.
  • Minimal Access Requirements: Only knowledge of the target project path and blob paths is required; no special permissions are needed.

How To Reproduce

Please add reproducibility information to this section: