Our assessment
We added platform to the blocklist of unsafe modules (trailofbits/fickling@351ed4d).
It was not possible to inject extra arguments to file without first monkey-patching platform._follow_symlinks with the pickle, as it always returns an absolute path. We independently hardened it with trailofbits/fickling@b9e690c to reduce the risk of obtaining direct module references while evading detection.
https://github.com/python/cpython/blob/6d1e9ceed3e70ebc39953f5ad4f20702ffa32119/Lib/platform.py#L687-L695
target = _follow_symlinks(target)
# "file" output is locale dependent: force the usage of the C locale
# to get deterministic behavior.
env = dict(os.environ, LC_ALL='C')
try:
# -b: do not prepend filenames to output lines (brief mode)
output = subprocess.check_output(['file', '-b', target],
stderr=subprocess.DEVNULL,
env=env)
Original report
Summary
A crafted pickle invoking platform._syscmd_file, platform.architecture, or platform.libc_ver passes check_safety() with Severity.LIKELY_SAFE and zero findings. During fickling.loads(), these functions invoke subprocess.check_output with attacker-controlled arguments or read arbitrary files from disk.
Clarification: The subprocess call uses a list argument (['file', '-b', target]), not shell=True, so the attacker controls the file path argument to the file command, not the command itself. The impact is subprocess invocation with attacker-controlled arguments and information disclosure (file type probing), not arbitrary command injection.
Affected versions
<= 0.1.9 (verified on upstream HEAD as of 2026-03-04)
Non-duplication check against published Fickling GHSAs
No published advisory covers platform module false-negative bypass. This follows the same structural pattern as GHSA-5hwf-rc88-82xm (missing modules in UNSAFE_IMPORTS) but covers a distinct set of functions.
Root cause
platform not in UNSAFE_IMPORTS denylist.
OvertlyBadEvals skips calls imported from stdlib modules.
UnusedVariables heuristic neutralized by making call result appear used (SETITEMS path).
Reproduction (clean upstream)
from unittest.mock import patch
import fickling
import fickling.fickle as op
from fickling.fickle import Pickled
from fickling.analysis import check_safety
pickled = Pickled([
op.Proto.create(4),
op.ShortBinUnicode('platform'),
op.ShortBinUnicode('_syscmd_file'),
op.StackGlobal(),
op.ShortBinUnicode('/etc/passwd'),
op.TupleOne(),
op.Reduce(),
op.Memoize(),
op.EmptyDict(),
op.ShortBinUnicode('init'),
op.ShortBinUnicode('x'),
op.SetItem(),
op.Mark(),
op.ShortBinUnicode('trace'),
op.BinGet(0),
op.SetItems(),
op.Stop(),
])
results = check_safety(pickled)
print(results.severity.name, len(results.results)) # LIKELY_SAFE 0
with patch('subprocess.check_output', return_value=b'ASCII text') as mock_sub:
fickling.loads(pickled.dumps())
print('subprocess called?', mock_sub.called) # True
print('args:', mock_sub.call_args[0]) # (['file', '-b', '/etc/passwd'],)
Additional affected functions (same pattern):
platform.architecture('/etc/passwd') — calls _syscmd_file internally
platform.libc_ver('/etc/passwd') — opens and reads arbitrary file contents
Minimal patch diff
--- a/fickling/fickle.py
+++ b/fickling/fickle.py
@@
+ "platform",
Validation after patch
- Same PoC flips to
LIKELY_OVERTLY_MALICIOUS
fickling.loads raises UnsafeFileError
subprocess.check_output is not called
Impact
- False-negative verdict:
check_safety() returns LIKELY_SAFE with zero findings for a pickle that invokes a subprocess with attacker-controlled arguments.
- Subprocess invocation:
platform._syscmd_file calls subprocess.check_output(['file', '-b', target]) where target is attacker-controlled. The file command reads file headers and returns type information, enabling file existence and type probing.
- File read:
platform.libc_ver opens and reads chunks of an attacker-specified file path.
References
Our assessment
We added
platformto the blocklist of unsafe modules (trailofbits/fickling@351ed4d).It was not possible to inject extra arguments to
filewithout first monkey-patchingplatform._follow_symlinkswith the pickle, as it always returns an absolute path. We independently hardened it with trailofbits/fickling@b9e690c to reduce the risk of obtaining direct module references while evading detection.https://github.com/python/cpython/blob/6d1e9ceed3e70ebc39953f5ad4f20702ffa32119/Lib/platform.py#L687-L695
Original report
Summary
A crafted pickle invoking
platform._syscmd_file,platform.architecture, orplatform.libc_verpassescheck_safety()withSeverity.LIKELY_SAFEand zero findings. Duringfickling.loads(), these functions invokesubprocess.check_outputwith attacker-controlled arguments or read arbitrary files from disk.Clarification: The subprocess call uses a list argument (
['file', '-b', target]), notshell=True, so the attacker controls the file path argument to thefilecommand, not the command itself. The impact is subprocess invocation with attacker-controlled arguments and information disclosure (file type probing), not arbitrary command injection.Affected versions
<= 0.1.9(verified on upstream HEAD as of 2026-03-04)Non-duplication check against published Fickling GHSAs
No published advisory covers
platformmodule false-negative bypass. This follows the same structural pattern as GHSA-5hwf-rc88-82xm (missing modules inUNSAFE_IMPORTS) but covers a distinct set of functions.Root cause
platformnot inUNSAFE_IMPORTSdenylist.OvertlyBadEvalsskips calls imported from stdlib modules.UnusedVariablesheuristic neutralized by making call result appear used (SETITEMSpath).Reproduction (clean upstream)
Additional affected functions (same pattern):
platform.architecture('/etc/passwd')— calls_syscmd_fileinternallyplatform.libc_ver('/etc/passwd')— opens and reads arbitrary file contentsMinimal patch diff
Validation after patch
LIKELY_OVERTLY_MALICIOUSfickling.loadsraisesUnsafeFileErrorsubprocess.check_outputis not calledImpact
check_safety()returnsLIKELY_SAFEwith zero findings for a pickle that invokes a subprocess with attacker-controlled arguments.platform._syscmd_filecallssubprocess.check_output(['file', '-b', target])wheretargetis attacker-controlled. Thefilecommand reads file headers and returns type information, enabling file existence and type probing.platform.libc_veropens and reads chunks of an attacker-specified file path.References