GHSA-CW26-7653-2RP5

Vulnerability from github – Published: 2026-05-05 19:53 – Updated: 2026-05-13 14:19
VLAI
Summary
exiftool-vendored vulnerable to argument injection via newline characters in tag names
Details

Impact

exiftool-vendored starts ExifTool in -stay_open True -@ - mode, where arguments are read from stdin one per line. In affected versions, several caller-supplied strings were interpolated into ExifTool arguments without rejecting line delimiters. A newline or carriage return inside one of those strings could split a single intended argument into multiple ExifTool arguments, allowing argument injection. The fix also rejects NUL bytes as unsafe control characters.

Applications that pass attacker-controlled strings to affected APIs may allow an attacker to make ExifTool read files accessible to the ExifTool process, or write output to attacker-chosen file system paths accessible to that process. No remote code execution has been demonstrated.

The reported write-path issue is caused by unsanitized tag keys. Tag values passed to ExifTool#write are not affected, because WriteTask already encodes whitespace characters in values (e.g. \n -> 
) before transmission.

Confirmed affected inputs:

  • Tag-name arguments / tag keys — keys of the tags object passed to ExifTool#write; entries of the retain option to ExifTool#deleteAllTags; entries of the numericTags option to ExifTool#read; the tagname argument to ExifTool#extractBinaryTag and #extractBinaryTagToBuffer.
  • Filename / path arguments to ExifTool#write, #read, #readRaw, #deleteAllTags, #rewriteAllTags, #extractBinaryTag, #extractBinaryTagToBuffer, and the binary-extraction convenience methods #extractJpgFromRaw, #extractPreview, and #extractThumbnail. path.resolve() does not strip newlines, so an application that accepts attacker-controlled filenames containing newline characters was vulnerable.
  • The imageHashType option to ExifTool#read. TypeScript types restrict this to a literal union, but JS callers or callers with weakened type checking could reach the sink.

Applications that only pass hardcoded strings for tag names, options, and filenames are not affected.

Patches

Fixed in v35.19.0. Two layers of defense:

  1. Per-site input validation. A new validateTagName helper rejects any tag-name string containing characters outside the ExifTool tag grammar (letters, digits, :, -, _, and the ExifTool modifiers *, ?, +, #). Applied at every tag-name interpolation site.
  2. Defense-in-depth at the command renderer. ExifToolTask.renderCommand now rejects any argument containing \r, \n, or \0 before it is sent to the ExifTool process. This catches injection via filename arguments, option values, and any future interpolation site that forgets the per-site validator.

Workarounds

Upgrade to v35.19.0 or later.

If upgrading immediately is not possible, reject untrusted strings containing control characters before passing them to the affected APIs. Conservative guard:

function assertSafeForExifTool(s: string): void {
  if (typeof s !== "string" || /[\x00-\x20=<>]/.test(s)) {
    throw new Error("Rejected unsafe string for ExifTool");
  }
}

Apply to tag names, retain / numericTags entries, binary-extraction tag names, filenames, and the imageHashType option. This is a denylist and is strictly weaker than the library's internal validator; it is sufficient to block the known PoCs but will accept strings that the library itself now rejects.

Resources

  • ExifTool -stay_open / argument-file documentation: https://exiftool.org/exiftool_pod.html#stay_open-FLAG
  • ExifTool tag-name reference: https://exiftool.org/TagNames/
  • CWE-88: Improper Neutralization of Argument Delimiters in a Command ('Argument Injection') — https://cwe.mitre.org/data/definitions/88.html

Credit

  • Reporter: Hank Tam
  • Affiliation: Independent
Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 35.18.0"
      },
      "package": {
        "ecosystem": "npm",
        "name": "exiftool-vendored"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "35.19.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-43893"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-88"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-05T19:53:47Z",
    "nvd_published_at": "2026-05-11T22:22:14Z",
    "severity": "HIGH"
  },
  "details": "### Impact\n\n`exiftool-vendored` starts ExifTool in `-stay_open True -@ -` mode, where arguments are read from stdin one per line. In affected versions, several caller-supplied strings were interpolated into ExifTool arguments without rejecting line delimiters. A newline or carriage return inside one of those strings could split a single intended argument into multiple ExifTool arguments, allowing argument injection. The fix also rejects NUL bytes as unsafe control characters.\n\nApplications that pass attacker-controlled strings to affected APIs may allow an attacker to make ExifTool read files accessible to the ExifTool process, or write output to attacker-chosen file system paths accessible to that process. No remote code execution has been demonstrated.\n\nThe reported write-path issue is caused by unsanitized tag **keys**. Tag **values** passed to `ExifTool#write` are not affected, because `WriteTask` already encodes whitespace characters in values (e.g. `\\n` -\u003e `\u0026#10;`) before transmission.\n\nConfirmed affected inputs:\n\n- **Tag-name arguments / tag keys** \u2014 keys of the `tags` object passed to `ExifTool#write`; entries of the `retain` option to `ExifTool#deleteAllTags`; entries of the `numericTags` option to `ExifTool#read`; the `tagname` argument to `ExifTool#extractBinaryTag` and `#extractBinaryTagToBuffer`.\n- **Filename / path arguments** to `ExifTool#write`, `#read`, `#readRaw`, `#deleteAllTags`, `#rewriteAllTags`, `#extractBinaryTag`, `#extractBinaryTagToBuffer`, and the binary-extraction convenience methods `#extractJpgFromRaw`, `#extractPreview`, and `#extractThumbnail`. `path.resolve()` does not strip newlines, so an application that accepts attacker-controlled filenames containing newline characters was vulnerable.\n- **The `imageHashType` option** to `ExifTool#read`. TypeScript types restrict this to a literal union, but JS callers or callers with weakened type checking could reach the sink.\n\nApplications that only pass hardcoded strings for tag names, options, and filenames are not affected.\n\n### Patches\n\nFixed in **v35.19.0**. Two layers of defense:\n\n1. **Per-site input validation.** A new `validateTagName` helper rejects any tag-name string containing characters outside the ExifTool tag grammar (letters, digits, `:`, `-`, `_`, and the ExifTool modifiers `*`, `?`, `+`, `#`). Applied at every tag-name interpolation site.\n2. **Defense-in-depth at the command renderer.** `ExifToolTask.renderCommand` now rejects _any_ argument containing `\\r`, `\\n`, or `\\0` before it is sent to the ExifTool process. This catches injection via filename arguments, option values, and any future interpolation site that forgets the per-site validator.\n\n### Workarounds\n\nUpgrade to v35.19.0 or later.\n\nIf upgrading immediately is not possible, reject untrusted strings containing control characters before passing them to the affected APIs. Conservative guard:\n\n```ts\nfunction assertSafeForExifTool(s: string): void {\n  if (typeof s !== \"string\" || /[\\x00-\\x20=\u003c\u003e]/.test(s)) {\n    throw new Error(\"Rejected unsafe string for ExifTool\");\n  }\n}\n```\n\nApply to tag names, `retain` / `numericTags` entries, binary-extraction tag names, filenames, and the `imageHashType` option. This is a denylist and is strictly weaker than the library\u0027s internal validator; it is sufficient to block the known PoCs but will accept strings that the library itself now rejects.\n\n### Resources\n\n- ExifTool `-stay_open` / argument-file documentation: https://exiftool.org/exiftool_pod.html#stay_open-FLAG\n- ExifTool tag-name reference: https://exiftool.org/TagNames/\n- CWE-88: Improper Neutralization of Argument Delimiters in a Command (\u0027Argument Injection\u0027) \u2014 https://cwe.mitre.org/data/definitions/88.html\n\n### Credit\n\n- Reporter: Hank Tam\n- Affiliation: Independent",
  "id": "GHSA-cw26-7653-2rp5",
  "modified": "2026-05-13T14:19:52Z",
  "published": "2026-05-05T19:53:47Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/photostructure/exiftool-vendored.js/security/advisories/GHSA-cw26-7653-2rp5"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-43893"
    },
    {
      "type": "WEB",
      "url": "https://exiftool.org/TagNames"
    },
    {
      "type": "WEB",
      "url": "https://exiftool.org/exiftool_pod.html#stay_open-FLAG"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/photostructure/exiftool-vendored.js"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "exiftool-vendored vulnerable to argument injection via newline characters in tag names"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…