GitHub Security Advisory: GHSA-5cxw-w2xg-2m8h
Package: fickling (PIP)
Severity: MODERATE (CVSS 0.0)
CWE: CWE-184: Incomplete List of Disallowed Inputs
Vulnerable versions: <= 0.1.9
Patched in: 0.1.10

Summary: fickling's `platform` module subprocess invocation evades `check_safety()` with `LIKELY_SAFE`

Details:
# Our assessment

We added `platform` to the blocklist of unsafe modules (https://github.com/trailofbits/fickling/commit/351ed4d4242b447c0ffd550bb66b40695f3f9975). 

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 https://github.com/trailofbits/fickling/commit/b9e690c5a57ee9cd341de947fc6151959f4ae359 to reduce the risk of obtaining direct module references while evading detection.

https://github.com/python/cpython/blob/6d1e9ceed3e70ebc39953f5ad4f20702ffa32119/Lib/platform.py#L687-L695
```python
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
1. `platform` not in `UNSAFE_IMPORTS` denylist.
2. `OvertlyBadEvals` skips calls imported from stdlib modules.
3. `UnusedVariables` heuristic neutralized by making call result appear used (`SETITEMS` path).

## Reproduction (clean upstream)
```python
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_s