| CVE | Vulnerability name | Date | Responsible Security Disclosure by | Vulnerabilities |
|---|---|---|---|---|
|
GHSA-x3xm-pxrv-jg7p
|
ScannerBleed |
2026-07-05 |
DavidCarliez (coordinated disclosure) and xet7 (fix)
![]() Did send detailed report with PoC! |
|
| Where | Details |
|---|---|
| Affected code |
models/fileValidation.js — the external scanner (antivirus) invocation in
isFileValid().
|
| Root cause |
When an admin has configured an external scanner command line with a {file}
placeholder, the uploaded file path was interpolated into the command and run through
asyncExec (promisify(exec)), which spawns /bin/sh -c
and interprets all shell metacharacters:
await asyncExec(externalCommandLine.replace("{file}", '"' + fileObj.path + '"'));
Wrapping the path in double quotes is not a shell boundary — inside double quotes the shell still expands $(...), backticks and \. A filename such as
$(touch /tmp/pwn).png or a`id`.png escaped the argument and
executed as the Wekan server process. Any authenticated user who can upload an attachment
could trigger it on servers with an external scanner configured. Same RCE class as
AvatarBleed (CVE-2026-52891), but in a code path that was never
covered by that fix. Unlike the sibling MIME-detection path (detectMimeFromFile,
which already uses execFile with no shell) and unlike the AvatarBleed fix
(which strips non-alphanumeric characters), this scanner path had zero sanitization.
|
| Fix |
POSIX single-quote-escape the interpolated file path via a new shellQuote()
helper (wrap in single quotes, escape embedded ' as '\''). Inside
single quotes the shell interprets no metacharacters, so a malicious filename can no longer
break out of the argument or inject commands, while the admin's arbitrary command line and
the exact on-disk path are both preserved.
|
| Timeline | Details |
|---|---|
| 2026-07-05 | Report received from DavidCarliez. |
| 2026-07-05 | Fixed at the upcoming WeKan release. |