Skip to content

Commit b4d33a3

Browse files
1 parent b81361c commit b4d33a3

2 files changed

Lines changed: 135 additions & 0 deletions

File tree

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-5cxw-w2xg-2m8h",
4+
"modified": "2026-03-13T20:58:10Z",
5+
"published": "2026-03-13T20:58:10Z",
6+
"aliases": [],
7+
"summary": "fickling's `platform` module subprocess invocation evades `check_safety()` with `LIKELY_SAFE`",
8+
"details": "# Our assessment\n\nWe added `platform` to the blocklist of unsafe modules (https://github.com/trailofbits/fickling/commit/351ed4d4242b447c0ffd550bb66b40695f3f9975). \n\nIt 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.\n\nhttps://github.com/python/cpython/blob/6d1e9ceed3e70ebc39953f5ad4f20702ffa32119/Lib/platform.py#L687-L695\n```python\ntarget = _follow_symlinks(target)\n# \"file\" output is locale dependent: force the usage of the C locale\n# to get deterministic behavior.\nenv = dict(os.environ, LC_ALL='C')\ntry:\n # -b: do not prepend filenames to output lines (brief mode)\n output = subprocess.check_output(['file', '-b', target],\n stderr=subprocess.DEVNULL,\n env=env)\n```\n\n# Original report\n\n## Summary\nA 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.\n\n**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.\n\n## Affected versions\n`<= 0.1.9` (verified on upstream HEAD as of 2026-03-04)\n\n## Non-duplication check against published Fickling GHSAs\nNo 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.\n\n## Root cause\n1. `platform` not in `UNSAFE_IMPORTS` denylist.\n2. `OvertlyBadEvals` skips calls imported from stdlib modules.\n3. `UnusedVariables` heuristic neutralized by making call result appear used (`SETITEMS` path).\n\n## Reproduction (clean upstream)\n```python\nfrom unittest.mock import patch\nimport fickling\nimport fickling.fickle as op\nfrom fickling.fickle import Pickled\nfrom fickling.analysis import check_safety\n\npickled = Pickled([\n op.Proto.create(4),\n op.ShortBinUnicode('platform'),\n op.ShortBinUnicode('_syscmd_file'),\n op.StackGlobal(),\n op.ShortBinUnicode('/etc/passwd'),\n op.TupleOne(),\n op.Reduce(),\n op.Memoize(),\n op.EmptyDict(),\n op.ShortBinUnicode('init'),\n op.ShortBinUnicode('x'),\n op.SetItem(),\n op.Mark(),\n op.ShortBinUnicode('trace'),\n op.BinGet(0),\n op.SetItems(),\n op.Stop(),\n])\n\nresults = check_safety(pickled)\nprint(results.severity.name, len(results.results)) # LIKELY_SAFE 0\n\nwith patch('subprocess.check_output', return_value=b'ASCII text') as mock_sub:\n fickling.loads(pickled.dumps())\n print('subprocess called?', mock_sub.called) # True\n print('args:', mock_sub.call_args[0]) # (['file', '-b', '/etc/passwd'],)\n```\n\nAdditional affected functions (same pattern):\n- `platform.architecture('/etc/passwd')` — calls `_syscmd_file` internally\n- `platform.libc_ver('/etc/passwd')` — opens and reads arbitrary file contents\n\n## Minimal patch diff\n```diff\n--- a/fickling/fickle.py\n+++ b/fickling/fickle.py\n@@\n+ \"platform\",\n```\n\n## Validation after patch\n- Same PoC flips to `LIKELY_OVERTLY_MALICIOUS`\n- `fickling.loads` raises `UnsafeFileError`\n- `subprocess.check_output` is not called\n\n## Impact\n- **False-negative verdict:** `check_safety()` returns `LIKELY_SAFE` with zero findings for a pickle that invokes a subprocess with attacker-controlled arguments.\n- **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.\n- **File read:** `platform.libc_ver` opens and reads chunks of an attacker-specified file path.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "PyPI",
19+
"name": "fickling"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "0.1.10"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 0.1.9"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/trailofbits/fickling/security/advisories/GHSA-5cxw-w2xg-2m8h"
43+
},
44+
{
45+
"type": "WEB",
46+
"url": "https://github.com/trailofbits/fickling/commit/351ed4d4242b447c0ffd550bb66b40695f3f9975"
47+
},
48+
{
49+
"type": "PACKAGE",
50+
"url": "https://github.com/trailofbits/fickling"
51+
},
52+
{
53+
"type": "WEB",
54+
"url": "https://github.com/trailofbits/fickling/releases/tag/v0.1.10"
55+
}
56+
],
57+
"database_specific": {
58+
"cwe_ids": [
59+
"CWE-184"
60+
],
61+
"severity": "MODERATE",
62+
"github_reviewed": true,
63+
"github_reviewed_at": "2026-03-13T20:58:10Z",
64+
"nvd_published_at": null
65+
}
66+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-7x23-j8gv-v54x",
4+
"modified": "2026-03-13T20:58:28Z",
5+
"published": "2026-03-13T20:58:28Z",
6+
"aliases": [
7+
"CVE-2026-32720"
8+
],
9+
"summary": "github.com/ctfer-io/monitoring Vulnerable to Improper Access Control",
10+
"details": "### Impact\n\nDue to a mis-written NetworkPolicy, a malicious actor can pivot from a component to any other namespace.\nThis breaks the security-by-default property expected as part of the deployment program, leading to a potential lateral movement.\n\n### Patch\n\nRemoving the `inter-ns` NetworkPolicy patches the vulnerability. If updates are not possible in production environments, we recommend to manually delete it and update as soon as possible.\n\n### Workaround\n\nGiven your context, delete the failing network policy that should be prefixed by `inter-ns-` in the monitoring namespace.\nYou can use the following to delete all matching network policy. If unsure of the outcome, please do it manually.\n\n```bash\nfor ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\\n' | grep '^monitoring-'); do\n kubectl -n \"$ns\" get networkpolicy -o name \\\n | grep '^networkpolicy.networking.k8s.io/inter-ns-' \\\n | xargs -r kubectl -n \"$ns\" delete\ndone\n```",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/ctfer-io/monitoring"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.2.1"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/ctfer-io/monitoring/security/advisories/GHSA-7x23-j8gv-v54x"
42+
},
43+
{
44+
"type": "WEB",
45+
"url": "https://github.com/ctfer-io/monitoring/pull/168"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/ctfer-io/monitoring/commit/5404a11863b32b14ee5c62d1215352ab519d4edb"
50+
},
51+
{
52+
"type": "PACKAGE",
53+
"url": "https://github.com/ctfer-io/monitoring"
54+
},
55+
{
56+
"type": "WEB",
57+
"url": "https://github.com/ctfer-io/monitoring/releases/tag/v0.2.1"
58+
}
59+
],
60+
"database_specific": {
61+
"cwe_ids": [
62+
"CWE-284"
63+
],
64+
"severity": "HIGH",
65+
"github_reviewed": true,
66+
"github_reviewed_at": "2026-03-13T20:58:28Z",
67+
"nvd_published_at": null
68+
}
69+
}

0 commit comments

Comments
 (0)