CVE-2026-50558
Penelope unsafe tar extraction allows arbitrary local file write via crafted session archive
Penelope Shell Handler is a post-exploitation shell handler for authorized security testing. Prior to 0.20.0, the Unix download() implementation in penelope.py used tar.extractall(local_download_folder) on tar archives returned by remote sessions without validating member paths, allowing a malicious or compromised session to write files outside the intended download directory and potentially overwrite ~/.penelope/peneloperc. This issue is fixed in version 0.20.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- Required
What an attacker can affect
- Confidentiality
- None
- Integrity
- High
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
5.9
Penelope unsafe tar extraction allows arbitrary local file write via crafted session archive
Penelope Shell Handler is a post-exploitation shell handler for authorized security testing. Prior to 0.20.0, the Unix download() implementation in penelope.py used tar.extractall(local_download_folder) on tar archives returned by remote sessions without validating member paths, allowing a malicious or compromised session to write files outside the intended download directory and potentially overwrite ~/.penelope/peneloperc. This issue is fixed in version 0.20.0.
- Record
CVE-2026-50558- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
EUVDEUVD-2026-50395
5.9
Penelope Shell Handler is a post-exploitation shell handler for authorized security testing. Prior to 0.20.0, the Unix download() implementation in penelope.py used tar.extractall(local_download_folder) on tar archives returned by remote sessions without validating member paths, allowing a malicious or compromised session to write files outside the intended download directory and potentially overwrite ~/.penelope/peneloperc. This issue is fixed in version 0.20.0.
- Record
EUVD-2026-50395- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:L - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-f42x-p2mx-hm8r
5.9
Penelope unsafe tar extraction allows arbitrary local file write via crafted session archive
Summary
Penelope versions prior to 0.19.3 extracted tar archives received from remote sessions without validating archive member paths. When using the affected Unix download path, a malicious or compromised remote session could return a crafted tar archive containing path traversal entries, such as ../, causing files to be written outside the intended download directory on the Penelope operator's machine.
The impact is limited to files writable by the user running Penelope. In some cases, this arbitrary file write could be chained to operator-side code execution if the attacker can overwrite a file that Penelope or the user later executes, such as ~/.penelope/peneloperc. The issue has been fixed in version 0.19.3 by rejecting unsafe archive paths during extraction.
Affected conditions
The issue requires the operator to use the Main Menu download command to download files from a malicious or compromised remote session that can influence the tar archive returned to Penelope. The Python agent download path is not affected in the same way because it does not rely on the remote tar command.
The vulnerable behavior is related to Python's historical tarfile extraction defaults. In Python versions before 3.14, TarFile.extractall() did not use the safer data extraction filter by default, so applications extracting untrusted tar archives needed to explicitly provide a safe extraction filter or perform their own path validation.
Python 3.14 changes the default extraction behavior to use the data filter, which rejects dangerous archive features such as absolute paths and paths outside the destination directory. Penelope 0.19.3 now performs explicit validation/rejection of unsafe archive paths so the fix does not depend on the Python runtime version.
Details
The vulnerable code is in the Unix download() implementation.
Penelope creates a local download directory:
local_download_folder = self.directory / "downloads"
Later, it opens a tar archive received from the remote session:
tar = tarfile.open(mode=mode, fileobj=tar_source)
Then it extracts all members without validating archive paths:
tar.extractall(local_download_folder)
Because member names are trusted, a malicious tar archive can contain paths such as:
../../../../../home/operator/.penelope/peneloperc
This escapes the intended local_download_folder and writes to an arbitrary path writable by the Penelope operator.
The same extraction block also suppresses Python's DeprecationWarning around unsafe tar extraction:
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=DeprecationWarning)
tar.extractall(local_download_folder)
The file-write impact can be chained with Penelope's rc loading behavior:
def load_rc():
RC = Path(options.basedir / "peneloperc")
try:
with open(RC, "r") as rc:
exec(rc.read(), globals())
By default, options.basedir is ~/.penelope, so the executed rc file is:
~/.penelope/peneloperc
Since session downloads are stored under ~/.penelope/sessions/<session>/downloads, a crafted tar member can traverse upward and plant or replace ~/.penelope/peneloperc. The planted Python code executes when Penelope starts again or when the operator runs reload.
PoC
The following reproduces the issue locally by simulating a malicious remote endpoint. The fake tar binary is placed first in PATH for the test shell, so when Penelope asks the remote session to run tar, the remote session returns a crafted archive with path traversal entries.
Start Penelope in Terminal 1:
penelope -p 4444 -U -C #No upgrade and session connection needed
<img width="1920" height="337" alt="path1" src="https://github.com/user-attachments/assets/c8cb2dd6-e6d5-43ce-b3a2-61005dbcf95c" />
Prepare the fake remote tar in Terminal 2:
mkdir -p /tmp/penelope-fakebin…
- Record
GHSA-f42x-p2mx-hm8r- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
NVD
5.9
Penelope Shell Handler is a post-exploitation shell handler for authorized security testing. Prior to 0.20.0, the Unix download() implementation in penelope.py used tar.extractall(local_download_folder) on tar archives returned by remote sessions without validating member paths, allowing a malicious or compromised session to write files outside the intended download directory and potentially overwrite ~/.penelope/peneloperc. This issue is fixed in version 0.20.0.
- Record
CVE-2026-50558- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
OSV
5.9
Penelope unsafe tar extraction allows arbitrary local file write via crafted session archive
Penelope Shell Handler is a post-exploitation shell handler for authorized security testing. Prior to 0.20.0, the Unix download() implementation in penelope.py used tar.extractall(local_download_folder) on tar archives returned by remote sessions without validating member paths, allowing a malicious or compromised session to write files outside the intended download directory and potentially overwrite ~/.penelope/peneloperc. This issue is fixed in version 0.20.0.
- Record
CVE-2026-50558- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVGHSA-f42x-p2mx-hm8r
5.9
Penelope unsafe tar extraction allows arbitrary local file write via crafted session archive
Summary
Penelope versions prior to 0.19.3 extracted tar archives received from remote sessions without validating archive member paths. When using the affected Unix download path, a malicious or compromised remote session could return a crafted tar archive containing path traversal entries, such as ../, causing files to be written outside the intended download directory on the Penelope operator's machine.
The impact is limited to files writable by the user running Penelope. In some cases, this arbitrary file write could be chained to operator-side code execution if the attacker can overwrite a file that Penelope or the user later executes, such as ~/.penelope/peneloperc. The issue has been fixed in version 0.19.3 by rejecting unsafe archive paths during extraction.
Affected conditions
The issue requires the operator to use the Main Menu download command to download files from a malicious or compromised remote session that can influence the tar archive returned to Penelope. The Python agent download path is not affected in the same way because it does not rely on the remote tar command.
The vulnerable behavior is related to Python's historical tarfile extraction defaults. In Python versions before 3.14, TarFile.extractall() did not use the safer data extraction filter by default, so applications extracting untrusted tar archives needed to explicitly provide a safe extraction filter or perform their own path validation.
Python 3.14 changes the default extraction behavior to use the data filter, which rejects dangerous archive features such as absolute paths and paths outside the destination directory. Penelope 0.19.3 now performs explicit validation/rejection of unsafe archive paths so the fix does not depend on the Python runtime version.
Details
The vulnerable code is in the Unix download() implementation.
Penelope creates a local download directory:
local_download_folder = self.directory / "downloads"
Later, it opens a tar archive received from the remote session:
tar = tarfile.open(mode=mode, fileobj=tar_source)
Then it extracts all members without validating archive paths:
tar.extractall(local_download_folder)
Because member names are trusted, a malicious tar archive can contain paths such as:
../../../../../home/operator/.penelope/peneloperc
This escapes the intended local_download_folder and writes to an arbitrary path writable by the Penelope operator.
The same extraction block also suppresses Python's DeprecationWarning around unsafe tar extraction:
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=DeprecationWarning)
tar.extractall(local_download_folder)
The file-write impact can be chained with Penelope's rc loading behavior:
def load_rc():
RC = Path(options.basedir / "peneloperc")
try:
with open(RC, "r") as rc:
exec(rc.read(), globals())
By default, options.basedir is ~/.penelope, so the executed rc file is:
~/.penelope/peneloperc
Since session downloads are stored under ~/.penelope/sessions/<session>/downloads, a crafted tar member can traverse upward and plant or replace ~/.penelope/peneloperc. The planted Python code executes when Penelope starts again or when the operator runs reload.
PoC
The following reproduces the issue locally by simulating a malicious remote endpoint. The fake tar binary is placed first in PATH for the test shell, so when Penelope asks the remote session to run tar, the remote session returns a crafted archive with path traversal entries.
Start Penelope in Terminal 1:
penelope -p 4444 -U -C #No upgrade and session connection needed
<img width="1920" height="337" alt="path1" src="https://github.com/user-attachments/assets/c8cb2dd6-e6d5-43ce-b3a2-61005dbcf95c" />
Prepare the fake remote tar in Terminal 2:
mkdir -p /tmp/penelope-fakebin…
- Record
GHSA-f42x-p2mx-hm8r- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:L - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVPYSEC-2026-3606
5.9
Penelope unsafe tar extraction allows arbitrary local file write via crafted session archive
Summary
Penelope versions prior to 0.19.3 extracted tar archives received from remote sessions without validating archive member paths. When using the affected Unix download path, a malicious or compromised remote session could return a crafted tar archive containing path traversal entries, such as ../, causing files to be written outside the intended download directory on the Penelope operator's machine.
The impact is limited to files writable by the user running Penelope. In some cases, this arbitrary file write could be chained to operator-side code execution if the attacker can overwrite a file that Penelope or the user later executes, such as ~/.penelope/peneloperc. The issue has been fixed in version 0.19.3 by rejecting unsafe archive paths during extraction.
Affected conditions
The issue requires the operator to use the Main Menu download command to download files from a malicious or compromised remote session that can influence the tar archive returned to Penelope. The Python agent download path is not affected in the same way because it does not rely on the remote tar command.
The vulnerable behavior is related to Python's historical tarfile extraction defaults. In Python versions before 3.14, TarFile.extractall() did not use the safer data extraction filter by default, so applications extracting untrusted tar archives needed to explicitly provide a safe extraction filter or perform their own path validation.
Python 3.14 changes the default extraction behavior to use the data filter, which rejects dangerous archive features such as absolute paths and paths outside the destination directory. Penelope 0.19.3 now performs explicit validation/rejection of unsafe archive paths so the fix does not depend on the Python runtime version.
Details
The vulnerable code is in the Unix download() implementation.
Penelope creates a local download directory:
local_download_folder = self.directory / "downloads"
Later, it opens a tar archive received from the remote session:
tar = tarfile.open(mode=mode, fileobj=tar_source)
Then it extracts all members without validating archive paths:
tar.extractall(local_download_folder)
Because member names are trusted, a malicious tar archive can contain paths such as:
../../../../../home/operator/.penelope/peneloperc
This escapes the intended local_download_folder and writes to an arbitrary path writable by the Penelope operator.
The same extraction block also suppresses Python's DeprecationWarning around unsafe tar extraction:
with warnings.catch_warnings():
warnings.simplefilter("ignore", category=DeprecationWarning)
tar.extractall(local_download_folder)
The file-write impact can be chained with Penelope's rc loading behavior:
def load_rc():
RC = Path(options.basedir / "peneloperc")
try:
with open(RC, "r") as rc:
exec(rc.read(), globals())
By default, options.basedir is ~/.penelope, so the executed rc file is:
~/.penelope/peneloperc
Since session downloads are stored under ~/.penelope/sessions/<session>/downloads, a crafted tar member can traverse upward and plant or replace ~/.penelope/peneloperc. The planted Python code executes when Penelope starts again or when the operator runs reload.
PoC
The following reproduces the issue locally by simulating a malicious remote endpoint. The fake tar binary is placed first in PATH for the test shell, so when Penelope asks the remote session to run tar, the remote session returns a crafted archive with path traversal entries.
Start Penelope in Terminal 1:
penelope -p 4444 -U -C #No upgrade and session connection needed
<img width="1920" height="337" alt="path1" src="https://github.com/user-attachments/assets/c8cb2dd6-e6d5-43ce-b3a2-61005dbcf95c" />
Prepare the fake remote tar in Terminal 2:
mkdir -p /tmp/penelope-fakebin…
- Record
PYSEC-2026-3606- CVSS 3.1
- 5.9 Medium
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:H/A:L - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
penelope-shell-handlerPyPI |
before 0.20.0 | 0.20.0 |
penelope-shell-handlerPyPI |
before 0.20.0, plus listed versions 0.15.00.18.00.19.1 |
0.20.0 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-50558 is a medium vulnerability (CVSS 5.9) in Brightio Penelope, published July 29, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.37%, the 30th percentile. Fixed in penelope-shell-handler 0.20.0.
References
github.com/brightio/penelope/security/advisories/GHSA-f42x-p2mx-hm8r
github.com/brightio/penelope/commit/a040afb5db32c7e80b5e8a2f9b2164cf911cfa62
github.com/brightio/penelope/releases/tag/v0.20.0
github.com/advisories/GHSA-f42x-p2mx-hm8r
github.com/CVEProject/cvelistV5/tree/main/cves/2026/50xxx/CVE-2026-50558.json
nvd.nist.gov/vuln/detail/CVE-2026-50558
github.com/brightio/penelope
pypi.org/project/penelope-shell-handler
Left out here: the rest of 3 source descriptions. The JSON record has them.