Skip to content
Heist/ feed
Back to feed
MediumFix available

PDFME has SSRF via Unvalidated URL Fetch in `getB64BasePdf` When `basePdf` Is Attacker-Controlled

Type: advisorySources: OSV

## Summary The `getB64BasePdf` function in `@pdfme/common` fetches arbitrary URLs via `fetch()` without any validation when `basePdf` is a non-data-URI string and `window` is defined. An attacker who can control the `basePdf` field of a template (e.g., through a web application that accepts user-supplied templates) can force the server or client to make requests to arbitrary internal or external endpoints, enabling Server-Side Request Forgery (SSRF) in SSR contexts or blind request forgery in browser contexts. ## Details The vulnerability exists in `packages/common/src/helper.ts:130-141`. When `getB64BasePdf` receives a string that does not start with `data:application/pdf;`, and `window` is defined, it passes the string directly to `fetch()`: ```typescript // packages/common/src/helper.ts:130-141 export const getB64BasePdf = async ( customPdf: ArrayBuffer | Uint8Array | string, ): Promise => { if ( typeof customPdf === 'string' && !customPdf.startsWith('data:application/pdf;') && typeof window !== 'undefined' ) { const response = await fetch(customPdf); // <-- No URL validation const blob = await response.blob(); return blob2Base64Pdf(blob); } // ... }; ``` The Zod schema for `basePdf` in `packages/common/src/schema.ts:133-135` accepts any string: ```typescript export const CustomPdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]); export const BasePdf = z.union([CustomPdf, BlankPdf]); ``` The `checkGenerateProps` function at `packages/common/src/helper.ts:279`

Products
@pdfme/common
Affected versions
Not specified
Fixed versions
5.5.10
CVEs
CVE-2026-82866
Confirmed fixed CVEs
Not specified
Updated in this feed
1 Nov 2026, 03:39 UTC · Revision 1

Source evidence

PDFME has SSRF via Unvalidated URL Fetch in `getB64BasePdf` When `basePdf` Is Attacker-Controlled

core-osv · Original source

Published 20 Mar 2026, 20:45 UTC

## Summary The `getB64BasePdf` function in `@pdfme/common` fetches arbitrary URLs via `fetch()` without any validation when `basePdf` is a non-data-URI string and `window` is defined. An attacker who can control the `basePdf` field of a template (e.g., through a web application that accepts user-supplied templates) can force the server or client to make requests to arbitrary internal or external endpoints, enabling Server-Side Request Forgery (SSRF) in SSR contexts or blind request forgery in browser contexts. ## Details The vulnerability exists in `packages/common/src/helper.ts:130-141`. When `getB64BasePdf` receives a string that does not start with `data:application/pdf;`, and `window` is defined, it passes the string directly to `fetch()`: ```typescript // packages/common/src/helper.ts:130-141 export const getB64BasePdf = async ( customPdf: ArrayBuffer | Uint8Array | string, ): Promise => { if ( typeof customPdf === 'string' && !customPdf.startsWith('data:application/pdf;') && typeof window !== 'undefined' ) { const response = await fetch(customPdf); // <-- No URL validation const blob = await response.blob(); return blob2Base64Pdf(blob); } // ... }; ``` The Zod schema for `basePdf` in `packages/common/src/schema.ts:133-135` accepts any string: ```typescript export const CustomPdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]); export const BasePdf = z.union([CustomPdf, BlankPdf]); ``` The `checkGenerateProps` function at `packages/common/src/helper.ts:279`

osv:GHSA-pgx6-7jcq-2qff

@pdfme/common

Fixed versions: 5.5.10

Complete source record
{
  "id": "d96474fd7e920ae0efb3eeb80c34bd5fa93d680000281bce6d9de6620c43bd74",
  "url": "https://osv.dev/vulnerability/GHSA-pgx6-7jcq-2qff",
  "method": "structured",
  "payload": {
    "kind": "advisory",
    "title": "PDFME has SSRF via Unvalidated URL Fetch in `getB64BasePdf` When `basePdf` Is Attacker-Controlled",
    "summary": "## Summary The `getB64BasePdf` function in `@pdfme/common` fetches arbitrary URLs via `fetch()` without any validation when `basePdf` is a non-data-URI string and `window` is defined. An attacker who can control the `basePdf` field of a template (e.g., through a web application that accepts user-supplied templates) can force the server or client to make requests to arbitrary internal or external endpoints, enabling Server-Side Request Forgery (SSRF) in SSR contexts or blind request forgery in browser contexts. ## Details The vulnerability exists in `packages/common/src/helper.ts:130-141`. When `getB64BasePdf` receives a string that does not start with `data:application/pdf;`, and `window` is defined, it passes the string directly to `fetch()`: ```typescript // packages/common/src/helper.ts:130-141 export const getB64BasePdf = async ( customPdf: ArrayBuffer | Uint8Array | string, ): Promise => { if ( typeof customPdf === 'string' && !customPdf.startsWith('data:application/pdf;') && typeof window !== 'undefined' ) { const response = await fetch(customPdf); // <-- No URL validation const blob = await response.blob(); return blob2Base64Pdf(blob); } // ... }; ``` The Zod schema for `basePdf` in `packages/common/src/schema.ts:133-135` accepts any string: ```typescript export const CustomPdf = z.union([z.string(), ArrayBufferSchema, Uint8ArraySchema]); export const BasePdf = z.union([CustomPdf, BlankPdf]); ``` The `checkGenerateProps` function at `packages/common/src/helper.ts:279` ",
    "evidence": "osv:GHSA-pgx6-7jcq-2qff",
    "products": [
      {
        "name": {
          "value": "@pdfme/common",
          "evidence": "/affected/0/package/name"
        },
        "prerequisites": [],
        "fixed_versions": [
          {
            "value": "5.5.10",
            "evidence": "/affected/0/ranges"
          }
        ],
        "affected_versions": []
      }
    ],
    "severity": "medium",
    "structured": {
      "id": "GHSA-pgx6-7jcq-2qff",
      "aliases": [
        "CVE-2026-82866",
        "GHSA-pgx6-7jcq-2qff"
      ],
      "metrics": [
        {
          "type": "CVSS_V3",
          "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N"
        }
      ],
      "affected": [
        {
          "ranges": [
            {
              "type": "SEMVER",
              "events": [
                {
                  "introduced": "0"
                },
                {
                  "fixed": "5.5.10"
                }
              ]
            }
          ],
          "package": {
            "name": "@pdfme/common",
            "purl": "pkg:npm/%40pdfme/common",
            "ecosystem": "npm"
          },
          "database_specific": {
            "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-pgx6-7jcq-2qff/GHSA-pgx6-7jcq-2qff.json",
            "last_known_affected_version_range": "<= 5.5.9"
          }
        }
      ],
      "modified": "2026-10-24T02:56:54.238112659Z",
      "provider": "osv",
      "references": [
        "https://github.com/pdfme/pdfme/security/advisories/GHSA-pgx6-7jcq-2qff",
        "https://github.com/pdfme/pdfme"
      ],
      "provider_metadata": {
        "cwe_ids": [
          "CWE-918"
        ],
        "severity": "MODERATE",
        "github_reviewed": true,
        "nvd_published_at": null,
        "github_reviewed_at": "2026-03-20T20:45:17Z"
      }
    },
    "related_cves": [
      {
        "value": "CVE-2026-82866",
        "evidence": "/aliases"
      }
    ],
    "security_relevant": true,
    "severity_evidence": "/severity/0/score"
  },
  "source_id": "core-osv",
  "document_id": 428185,
  "published_at": "2026-03-20T20:45:17+00:00"
}