exiftool-vendored CVE-2026-43893
HIGHSeverity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N
Lifecycle Timeline
2Blast Radius
ecosystem impact- 1 npm packages depend on exiftool-vendored (1 direct, 0 indirect)
Ecosystem-wide dependent count for version 35.19.0.
DescriptionGitHub Advisory
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
tagsobject passed toExifTool#write; entries of theretainoption toExifTool#deleteAllTags; entries of thenumericTagsoption toExifTool#read; thetagnameargument toExifTool#extractBinaryTagand#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
imageHashTypeoption toExifTool#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:
- Per-site input validation. A new
validateTagNamehelper 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. - Defense-in-depth at the command renderer.
ExifToolTask.renderCommandnow rejects _any_ argument containing\r,\n, or\0before 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
AnalysisAI
Argument injection in exiftool-vendored npm package allows remote attackers to perform unauthorized file reads or writes via newline characters in tag names, filenames, or options. The vulnerability affects applications using exiftool-vendored ≤ 35.18.0 that pass attacker-controlled strings to ExifTool APIs without sanitization. Exploitation enables attackers to manipulate ExifTool's command-line arguments by injecting newlines into supposedly single-argument strings, breaking out of intended argument boundaries. While no remote code execution has been demonstrated, the CVSS 8.2 HIGH score reflects the network attack vector, low complexity, and lack of authentication or user interaction requirements. Fixed in version 35.19.0 with dual-layer validation rejecting control characters in both tag names and the command renderer. No public exploit code or active exploitation confirmed at time of analysis.
Technical ContextAI
The exiftool-vendored npm package (CPE: pkg:npm/exiftool-vendored) wraps the ExifTool command-line utility in a Node.js interface. It communicates with ExifTool via the -stay_open True -@ - mode, where ExifTool reads arguments from stdin, expecting one argument per line. This vulnerability (CWE-88: Improper Neutralization of Argument Delimiters in a Command) arises because the library interpolated caller-supplied strings directly into ExifTool command arguments without sanitizing newline characters (\n, \r) or NUL bytes (\0). An attacker embedding these control characters can split a single intended argument into multiple arguments, effectively injecting arbitrary ExifTool command-line flags or parameters. The affected code paths include tag-name processing in metadata write operations, filename handling across read/write/extract methods, and option values like imageHashType. The package's TypeScript type system provides some protection for option enums, but JavaScript callers or applications with relaxed type checking can bypass these constraints. The fix introduces validateTagName to enforce ExifTool's tag grammar (alphanumerics plus :, -, _, *, ?, +, #) and a global argument validator in ExifToolTask.renderCommand that rejects any argument containing \r, \n, or \0 before transmission to the ExifTool subprocess.
RemediationAI
Upgrade exiftool-vendored to version 35.19.0 or later, which implements validateTagName for tag-name inputs and ExifToolTask.renderCommand argument validation rejecting \r, \n, and \0 characters. Update via npm with 'npm install exiftool-vendored@latest' or specify '>=35.19.0' in package.json dependencies. For environments where immediate upgrade is not feasible, implement input validation using the vendor-recommended conservative guard that rejects strings containing control characters (\x00-\x20) and potentially unsafe characters (=<>) before passing to ExifTool#write, #read, #readRaw, #deleteAllTags, #rewriteAllTags, #extractBinaryTag, #extractBinaryTagToBuffer, and binary-extraction methods (#extractJpgFromRaw, #extractPreview, #extractThumbnail). Apply validation to all tag names, retain/numericTags option entries, filenames, and imageHashType options. Note this workaround is a denylist approach weaker than the library's allowlist validator and should be considered temporary. Applications that exclusively use hardcoded strings for tag names, filenames, and options require no immediate action but should still upgrade as a defense-in-depth measure. Review application code to identify any code paths accepting user input for these parameters. Full advisory and code-level details at https://github.com/photostructure/exiftool-vendored.js/security/advisories/GHSA-cw26-7653-2rp5.
Share
External POC / Exploit Code
Leaving vuln.today
GHSA-cw26-7653-2rp5