Skip to content

Commit 3ab6996

Browse files
1 parent 6e14d38 commit 3ab6996

5 files changed

Lines changed: 325 additions & 0 deletions

File tree

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-2v8p-fqpx-2q3w",
4+
"modified": "2026-07-02T20:44:57Z",
5+
"published": "2026-07-02T20:44:57Z",
6+
"aliases": [],
7+
"summary": "jxl-oxide: integer subtraction overflow panic in cluster_from_table via crafted JXL input (DoS)",
8+
"details": "### Summary\nLogic bug in `decode_simple_table_slow` may cause integer arithmetic overflow when decoding Modular image with certain kind of MA tree, which may panic with `overflow-checks` enabled.\n\n### Impact\nDenial of service: any application passing untrusted JXL data to `JxlImage::render_frame` (or equivalent) can be\ncrashed. Affects all builds with overflow checks enabled, which includes debug builds and any release build\nthat sets `overflow-checks = true` in Cargo.toml or `[profile.*]`.\n\nNo memory corruption is possible — the panic fires before any unsafe code is reached.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "crates.io",
19+
"name": "jxl-modular"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "0.11.3"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 0.11.2"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/tirr-c/jxl-oxide/security/advisories/GHSA-2v8p-fqpx-2q3w"
43+
},
44+
{
45+
"type": "PACKAGE",
46+
"url": "https://github.com/tirr-c/jxl-oxide"
47+
}
48+
],
49+
"database_specific": {
50+
"cwe_ids": [
51+
"CWE-190"
52+
],
53+
"severity": "MODERATE",
54+
"github_reviewed": true,
55+
"github_reviewed_at": "2026-07-02T20:44:57Z",
56+
"nvd_published_at": null
57+
}
58+
}
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-5pmv-rx8r-wmv5",
4+
"modified": "2026-07-02T20:45:59Z",
5+
"published": "2026-07-02T20:45:59Z",
6+
"aliases": [
7+
"CVE-2026-52834"
8+
],
9+
"summary": "jxl-grid on 32-bit platforms has an out-of-bounds writes due to integer overflow",
10+
"details": "### Summary\n\nOn 32-bit platforms, decoding a crafted image may lead to out-of-bounds writes due to integer overflow in length calculation.\n\n### Details & PoC\n\nThe test listed below fail under miri with command `cargo +nightly miri test --release -p jxl-grid`\n\nOr you can use Address Sanitizer, which ignores Rust-specific UB like aliasing but still flags out-of-bounds accesses:\n\n`RUSTFLAGS=-Zsanitizer=address cargo +nightly test -Zbuild-std -p jxl-grid --release --target x86_64-unknown-linux-gnu`\n\nThe following tests should be appended to `crates/jxl-grid/src/test/subgrids.rs`:\n\n```rust\nmod miri_ub {\n use super::*;\n\n // `AlignedGrid::with_alloc_tracker` computes `width * height` unchecked. In release, overflow\n // can create a tiny backing buffer for huge logical dimensions.\n #[test]\n fn aligned_grid_dimension_product_overflows() {\n let width = usize::MAX / 2 + 1;\n let mut grid = AlignedGrid::<u8>::with_alloc_tracker(width, 2, None).unwrap();\n let mut subgrid = grid.as_subgrid_mut();\n *subgrid.get_mut(0, 1) = 1;\n std::hint::black_box(grid);\n }\n}\n```\n\nThis issue can be reachable through decoding a crafted image in two ways:\n\n1. **Huge actual frame**\n A frame such as `65536 x 65536` passes the current frame area limit (`2^32 <= 2^40`) but overflows `usize` element count on 32-bit. Rendering then allocates too-small `AlignedGrid`s in modular/VarDCT/filter paths and later writes through mutable subgrids.\n\n2. **Huge canvas plus tiny cropped frame**\n This is the more practical “small payload, huge logical output” case. A bitstream-controlled frame crop can be tiny, but if the canvas/default requested region is huge, composition can allocate an output grid sized to the canvas/ROI at crates/jxl-render/src/blend.rs. That is bitstream frame cropping, not API crop. With a 32-bit target and a full requested image region whose area overflows, this can happen through ordinary `render_frame()`.\n\n### Impact\n\nOn 32-bit platforms this can cause out-of-bounds writes with attacker-controlled data when decoding a crafted JPEG XL image. This could allow arbitrary code execution.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:H"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "crates.io",
21+
"name": "jxl-grid"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "0.6.2"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 0.6.1"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/tirr-c/jxl-oxide/security/advisories/GHSA-5pmv-rx8r-wmv5"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/tirr-c/jxl-oxide"
49+
},
50+
{
51+
"type": "WEB",
52+
"url": "https://rustsec.org/advisories/RUSTSEC-2026-0151.html"
53+
}
54+
],
55+
"database_specific": {
56+
"cwe_ids": [
57+
"CWE-122",
58+
"CWE-131",
59+
"CWE-190"
60+
],
61+
"severity": "HIGH",
62+
"github_reviewed": true,
63+
"github_reviewed_at": "2026-07-02T20:45:59Z",
64+
"nvd_published_at": null
65+
}
66+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-66m8-c62j-h6v5",
4+
"modified": "2026-07-02T20:45:10Z",
5+
"published": "2026-07-02T20:45:10Z",
6+
"aliases": [],
7+
"summary": "jxl-oxide: `FrameBuffer::new` creates out-of-bounds slices on overflow",
8+
"details": "### Summary\n`jxl-oxide` exposes a public safe API that can construct an undersized `FrameBuffer` due to unchecked `usize` multiplication, which immediately trigger panic while initializing the buffer in normal decoding path.\n\nAdditionally, calling the safe grouped buffer accessors afterward can create invalid oversized slices from a much smaller allocation, causing undefined behavior; however normal decoding path never reaches UB, because these methods are never used within `jxl-oxide`.\n\n### Impact\nOn 32-bit platforms this can cause panic by accessing out-of-range indices, making it a DoS vulnerability.",
9+
"severity": [
10+
{
11+
"type": "CVSS_V3",
12+
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
13+
}
14+
],
15+
"affected": [
16+
{
17+
"package": {
18+
"ecosystem": "crates.io",
19+
"name": "jxl-oxide"
20+
},
21+
"ranges": [
22+
{
23+
"type": "ECOSYSTEM",
24+
"events": [
25+
{
26+
"introduced": "0"
27+
},
28+
{
29+
"fixed": "0.12.6"
30+
}
31+
]
32+
}
33+
],
34+
"database_specific": {
35+
"last_known_affected_version_range": "<= 0.12.5"
36+
}
37+
}
38+
],
39+
"references": [
40+
{
41+
"type": "WEB",
42+
"url": "https://github.com/tirr-c/jxl-oxide/security/advisories/GHSA-66m8-c62j-h6v5"
43+
},
44+
{
45+
"type": "PACKAGE",
46+
"url": "https://github.com/tirr-c/jxl-oxide"
47+
}
48+
],
49+
"database_specific": {
50+
"cwe_ids": [
51+
"CWE-131",
52+
"CWE-190"
53+
],
54+
"severity": "MODERATE",
55+
"github_reviewed": true,
56+
"github_reviewed_at": "2026-07-02T20:45:10Z",
57+
"nvd_published_at": null
58+
}
59+
}
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-mm6c-5j6x-hq8m",
4+
"modified": "2026-07-02T20:46:43Z",
5+
"published": "2026-07-02T20:46:42Z",
6+
"aliases": [
7+
"CVE-2026-52792"
8+
],
9+
"summary": "Algernon vulnerable to server-side script source disclosure on Windows via NTFS filename",
10+
"details": "### Summary\n\nAlgernon selects its file handler from `filepath.Ext()` (engine/handlers.go:134), which does not treat the NTFS-equivalent names `x.lua::$DATA`, `x.lua.`, or `x.lua ` as `.lua`. On Windows, an unauthenticated client appends one of these suffixes to any server-side script on a public path and receives its raw source instead of executed output, leaking embedded secrets such as database credentials and the `SetCookieSecret` value.\n\nLinux and macOS hosts are unaffected.\n\n### Preconditions\n\n- Algernon runs on a Windows host (NTFS filesystem).\n- The instance serves at least one server-side script (`.lua`, `.tl`, `.po2`, `.amber`, `.frm`).\n- The script sits on a public path, or no auth backend is configured (`--nodb`, `--simple`, or default no-DB).\n- HTTP/HTTPS reachability to the server.\n\n### Details\n\n```go\n// engine/handlers.go:133\nlowercaseFilename := strings.ToLower(filename)\next := filepath.Ext(lowercaseFilename) // \"index.lua::$data\" -> \".lua::$data\", not \".lua\" [offending]\n...\nif ac.dispatchRenderer(w, req, filename, ext) { // ext unrecognised, returns false\n return\n}\nswitch ext {\ncase \".lua\", \".tl\": // execute the script -- never reached for the equivalent forms\n // ... RunLua ...\ndefault:\n // control reaches the raw-file branch below\n}\n```\n\n```go\n// engine/handlers.go:452\nf, err := os.Open(filename) // NTFS resolves \"index.lua::$DATA\" to index.lua's data stream\n...\n// engine/handlers.go:479\nif dataBlock, err := ac.ReadAndLogErrors(w, filename, ext); err == nil {\n dataBlock.ToClient(w, req, filename, ac.ClientCanGzip(req), gzipThreshold) // raw source to client\n}\n```\n\nThe request path reaches `FilePage` through `URL2filename` (utils/files.go:24), which rejects only `..`; a `:`, a trailing `.`, and a trailing space all pass through into `filename`. `filepath.Ext` does an exact suffix match, so `.lua::$data`, `.`, and `.lua ` are not equal to `.lua` or `.tl`. The renderer registry and the execute case are both skipped and control falls to the `default` branch.\n\nThe default branch opens `filename` with `os.Open` and streams the bytes verbatim. On Windows, NTFS canonicalises the alternate-data-stream suffix `::$DATA`, a trailing dot, and a trailing space back to the underlying file, so the bytes returned are the real script source. The missing check: Algernon never rejects or canonicalises Windows-equivalent filenames before choosing a handler.\n\n### Proof of concept\n\n**Setup**\n\n1. Build Algernon from source on a Windows host:\n\n ```powershell\n git clone https://github.com/xyproto/algernon\n cd algernon\n git checkout v1.17.8\n go build -o algernon.exe .\n ```\n\n2. Create a web root with a script that embeds secrets, exactly as a real handler would:\n\n ```powershell\n New-Item -ItemType Directory webroot | Out-Null\n Set-Content webroot\\index.lua @'\n -- db = POSTGRES(\"postgres://app:S3cr3t@db/prod\")\n SetCookieSecret(\"hardcoded-session-key\")\n print(\"<h1>hello</h1>\")\n '@\n ```\n\n3. Serve the directory over plain HTTP with no auth backend (run in its own window):\n\n ```powershell\n .\\algernon.exe --httponly --noninteractive --nodb --addr ':8088' --dir .\\webroot\n ```\n\n**Exploit**\n\n1. Request the script normally. It executes, and the source is not disclosed:\n\n ```powershell\n curl.exe -s http://127.0.0.1:8088/index.lua\n ```\n\n Expected: `<h1>hello</h1>`. The DSN and cookie secret are absent from the response.\n\n2. Request the same script through its NTFS `::$DATA` stream. Algernon returns the raw source:\n\n ```powershell\n curl.exe -s --path-as-is 'http://127.0.0.1:8088/index.lua::$DATA'\n ```\n\n Expected: HTTP 200, `Content-Type: application/octet-stream`, body is the verbatim Lua source including `SetCookieSecret(\"hardcoded-session-key\")` and the Postgres DSN.\n\n3. The trailing-dot and trailing-space forms leak the same source:\n\n ```powershell\n curl.exe -s --path-as-is 'http://127.0.0.1:8088/index.lua.'\n curl.exe -s --path-as-is 'http://127.0.0.1:8088/index.lua%20'\n ```\n\n Expected: identical raw-source response for both.\n\n### Impact\n\n- **Confidentiality:** Reads the verbatim source of any public-path server-side script, exposing hardcoded DB credentials, API keys, and `SetCookieSecret(...)` values.\n- **Authentication:** A disclosed `SetCookieSecret` value lets an unauthenticated attacker forge session cookies and log in as any user.\n\n### Suggestions to fix\n\n> _This has not been tested - it is illustrative only._\n\nReject request paths whose final segment uses a Windows-equivalent form (alternate data stream, trailing dot, or trailing space) before extension dispatch.\n\n```diff\n func (ac *Config) FilePage(w http.ResponseWriter, req *http.Request, filename, luaDataFilename string) {\n+\t// Reject Windows filename-equivalent forms that alias a different file\n+\t// than filepath.Ext sees (e.g. \"x.lua::$DATA\", \"x.lua.\", \"x.lua \").\n+\tif base := filepath.Base(filename); strings.ContainsRune(base, ':') ||\n+\t\tstrings.HasSuffix(base, \".\") || strings.HasSuffix(base, \" \") {\n+\t\thttp.NotFound(w, req)\n+\t\treturn\n+\t}\n \tif ac.quitAfterFirstRequest {\n \t\tgo ac.quitSoon(\"Quit after first request\", defaultSoonDuration)\n \t}\n```",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Go",
21+
"name": "github.com/xyproto/algernon"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "1.17.9"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 1.17.8"
38+
}
39+
}
40+
],
41+
"references": [
42+
{
43+
"type": "WEB",
44+
"url": "https://github.com/xyproto/algernon/security/advisories/GHSA-mm6c-5j6x-hq8m"
45+
},
46+
{
47+
"type": "PACKAGE",
48+
"url": "https://github.com/xyproto/algernon"
49+
}
50+
],
51+
"database_specific": {
52+
"cwe_ids": [
53+
"CWE-69"
54+
],
55+
"severity": "HIGH",
56+
"github_reviewed": true,
57+
"github_reviewed_at": "2026-07-02T20:46:42Z",
58+
"nvd_published_at": null
59+
}
60+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-q8r6-xj3f-wrrm",
4+
"modified": "2026-07-02T20:47:21Z",
5+
"published": "2026-07-02T20:47:21Z",
6+
"aliases": [
7+
"CVE-2026-49284"
8+
],
9+
"summary": "SimpleSAMLphp SP accepts a response from an unexpected IdP when unsigned `Response/InResponseTo` is combined with a signed assertion lacking `SubjectConfirmationData/InResponseTo`",
10+
"details": "## Summary\n\nSimpleSAMLphp's SAML SP ACS path does not enforce the IdP selected for an SP-initiated login. If a saved SP state contains `ExpectedIssuer = IdP A`, but the ACS receives a valid response from `IdP B`, the code logs a warning and continues processing instead of rejecting the response.\n\nThat behavior becomes security-relevant when combined with the response-processing rule that accepts an unsigned `samlp:Response/@InResponseTo` outside the signed assertion whenever the signed assertion's `SubjectConfirmationData` does not carry its own `InResponseTo`. A response issued by one trusted IdP can therefore be bound to SP state created for another IdP.\n\n## Impact\n\nIn a multi-IdP deployment, a lower-trust IdP can satisfy SP state created for a different expected IdP. This can bypass an SP flow that intentionally routes the user to a specific IdP, including deployments that set `enable_unsolicited` to `false` to prevent IdP-initiated logins.\n\nThe impact is highest when the SP trusts multiple IdPs with different assurance levels, tenant boundaries, or attribute namespaces, and application authorization depends on the selected/expected IdP. In those deployments this is an authentication/authorization bypass candidate. Impact strongly depends on whether an attacker can obtain a signed IdP-initiated assertion from a lower-trust trusted IdP and whether the downstream application maps identifiers globally.",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "Packagist",
21+
"name": "simplesamlphp/simplesamlphp"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "2.5.0"
29+
},
30+
{
31+
"fixed": "2.5.2"
32+
}
33+
]
34+
}
35+
],
36+
"database_specific": {
37+
"last_known_affected_version_range": "<= 2.5.1"
38+
}
39+
},
40+
{
41+
"package": {
42+
"ecosystem": "Packagist",
43+
"name": "simplesamlphp/simplesamlphp"
44+
},
45+
"ranges": [
46+
{
47+
"type": "ECOSYSTEM",
48+
"events": [
49+
{
50+
"introduced": "0"
51+
},
52+
{
53+
"fixed": "2.4.7"
54+
}
55+
]
56+
}
57+
],
58+
"database_specific": {
59+
"last_known_affected_version_range": "<= 2.4.6"
60+
}
61+
}
62+
],
63+
"references": [
64+
{
65+
"type": "WEB",
66+
"url": "https://github.com/simplesamlphp/simplesamlphp/security/advisories/GHSA-q8r6-xj3f-wrrm"
67+
},
68+
{
69+
"type": "PACKAGE",
70+
"url": "https://github.com/simplesamlphp/simplesamlphp"
71+
}
72+
],
73+
"database_specific": {
74+
"cwe_ids": [
75+
"CWE-345"
76+
],
77+
"severity": "HIGH",
78+
"github_reviewed": true,
79+
"github_reviewed_at": "2026-07-02T20:47:21Z",
80+
"nvd_published_at": null
81+
}
82+
}

0 commit comments

Comments
 (0)