From e8d8d1e8b202e1192a68d280ea556a3cffeda658 Mon Sep 17 00:00:00 2001 From: "M.Hoffmann" Date: Thu, 22 Oct 2026 04:28:53 -0300 Subject: [PATCH 1/2] fix(gleam-website): node 24.22.1, the October 2026 security release The October 2026 Node.js security release (nodejs.org/en/blog/vulnerability/ october-2026-security-releases, 2026-10-21) fixes 10 vulnerabilities, 4 of them high: a Brotli decoder out-of-bounds write with remote code execution (CVE-2026-111497) and TLS hostname checks that can accept the wrong server. 24.21.0, the nodejs of nixos-unstable on 2026-10-22, is affected; 24.22.1 has the fixes. nixpkgs does not ship 24.22.1 yet. nodejs-bin.nix takes the official nodejs.org build of 24.22.1 for x86_64-linux, aarch64-linux and aarch64-darwin, pinned by the sha256 of the release's SHASUMS256.txt (autoPatchelf on Linux). Only toolsFor gets it: an overlay of pkgs.nodejs would rebuild erlang and webkitgtk through gleam. checks.node-version fails at evaluation below 24.22.1 and runs the binary in the sandbox, because the scanners' databases (osv.dev, nodejs/security-wg) do not list these CVEs yet. nodejs leaves lab.json's headline: the card reads nixpkgs' nodejs, which is now not the node of this shell. Drop nodejs-bin.nix when nixpkgs has nodejs >= 24.22.1. Tested: nix flake check --no-update-lock-file --print-build-logs . in labs/gleam-website (exit 0: node-version v24.22.1, versions, smoke); nix develop: node v24.22.1, npm 11.19.1; nixpkgs-fmt --check, statix check, deadnix --fail (exit 0); just --list Co-Authored-By: Claude --- labs/gleam-website/README.md | 2 +- labs/gleam-website/flake.nix | 18 +++++++++++++- labs/gleam-website/lab.json | 2 +- labs/gleam-website/nodejs-bin.nix | 41 +++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 labs/gleam-website/nodejs-bin.nix diff --git a/labs/gleam-website/README.md b/labs/gleam-website/README.md index 0374269..8c35bb7 100644 --- a/labs/gleam-website/README.md +++ b/labs/gleam-website/README.md @@ -43,7 +43,7 @@ Lustre application, `src//prerender.gleam` prints the first render as `dist | Type | Program | | :--------- | :-----: | | Language | [Gleam 1.19](https://gleam.run/) on the JavaScript target; sites use [Lustre](https://lustre.build) from Hex | -| Runtime | [Node.js 24](https://nodejs.org/) (`gleam test`, `gleam run` for the prerender) | +| Runtime | [Node.js 24.22.1](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases), the official nodejs.org build pinned by sha256 in `nodejs-bin.nix` until nixpkgs ships it (`gleam test`, `gleam run` for the prerender); `checks.node-version` fails below 24.22.1 | | Bundler | [esbuild](https://esbuild.github.io/) | | Scripting | [just](https://github.com/casey/just), python 3 | | Reuse | `lib..tools`, `packages..{gleam, esbuild}`, `checks..{smoke, versions}` | diff --git a/labs/gleam-website/flake.nix b/labs/gleam-website/flake.nix index 26b79ba..bbcbb2f 100644 --- a/labs/gleam-website/flake.nix +++ b/labs/gleam-website/flake.nix @@ -13,9 +13,24 @@ # The toolchain of picasso's own site/ (Gleam + Lustre, bundled by esbuild). A site pins its # Hex packages by checksum in its manifest.toml; everything else comes from here. + nodeFor = pkgs: pkgs.callPackage ./nodejs-bin.nix { }; + + # The October 2026 security release (nodejs.org/en/blog/vulnerability/october-2026-security-releases): + # the scanners' databases lag the advisory, so the minimum is stated here and checked in CI. + nodeVersionFor = pkgs: + let node = nodeFor pkgs; in + assert lib.assertMsg (lib.versionAtLeast node.version "24.22.1") + "gleam-website: node ${node.version} is below 24.22.1, the October 2026 security release"; + pkgs.runCommand "gleam-website-node-version" { nativeBuildInputs = [ node ]; } '' + node --version | tee "$out" + ''; + toolsFor = pkgs: with pkgs; [ gleam - nodejs # gleam test, gleam run (the prerender) and the bundle check run on node + # gleam test, gleam run (the prerender) and the bundle check run on node: the official + # 24.22.1 build (nodejs-bin.nix), the October 2026 security release, until nixpkgs ships it. + # Only this list gets it: an overlay of pkgs.nodejs would rebuild erlang and webkitgtk. + (nodeFor pkgs) esbuild just python3 # the small generators and checks a site keeps next to its Gleam code @@ -89,6 +104,7 @@ checks = forAll (pkgs: { lab-json = labCardFor pkgs; + node-version = nodeVersionFor pkgs; versions = self.packages.${pkgs.stdenv.hostPlatform.system}.versions; smoke = self.packages.${pkgs.stdenv.hostPlatform.system}.smoke; }); diff --git a/labs/gleam-website/lab.json b/labs/gleam-website/lab.json index 702091f..574414d 100644 --- a/labs/gleam-website/lab.json +++ b/labs/gleam-website/lab.json @@ -1,4 +1,4 @@ { "summary": "Gleam on the JavaScript target, node, esbuild, just: static sites in picasso's style", - "headline": ["gleam", "nodejs", "esbuild", "just"] + "headline": ["gleam", "esbuild", "just"] } diff --git a/labs/gleam-website/nodejs-bin.nix b/labs/gleam-website/nodejs-bin.nix new file mode 100644 index 0000000..2ca9589 --- /dev/null +++ b/labs/gleam-website/nodejs-bin.nix @@ -0,0 +1,41 @@ +# Node.js 24.22.1, the official build from nodejs.org, in place of nixpkgs' nodejs until nixpkgs +# ships it: 24.22.1 is the October 2026 security release (Brotli RCE, TLS hostname bypass, +# nodejs.org/en/blog/vulnerability/october-2026-security-releases), and nixos-unstable is still on +# 24.21.0 (2026-10-22). The hashes are the release's SHASUMS256.txt. Drop this file, and the +# overlay in flake.nix, once `nix flake update` brings nodejs >= 24.22.1. +{ lib, stdenv, fetchurl, autoPatchelfHook }: + +let + version = "24.22.1"; + builds = { + x86_64-linux = { arch = "linux-x64"; sha256 = "6c172a9ab6718f7b801fb5a7bd486af2ee5e32758086a04b84fcce2aa77095e6"; }; + aarch64-linux = { arch = "linux-arm64"; sha256 = "dbabf7a1cbf947e6059ffad2c27b80041db97dea1e553b62afdee7f13fca336e"; }; + aarch64-darwin = { arch = "darwin-arm64"; sha256 = "654ba79de6155647e22321932b45f2a1ccb705976cc337c9b8e278beb085a628"; }; + }; + build = builds.${stdenv.hostPlatform.system} or (throw "nodejs-bin: no official build for ${stdenv.hostPlatform.system}"); +in +stdenv.mkDerivation { + pname = "nodejs"; + inherit version; + src = fetchurl { + url = "https://nodejs.org/dist/v${version}/node-v${version}-${build.arch}.tar.xz"; + inherit (build) sha256; + }; + nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook ]; + buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ stdenv.cc.cc.lib ]; + dontConfigure = true; + dontBuild = true; + installPhase = '' + runHook preInstall + mkdir -p $out + cp -r bin include lib share $out/ + runHook postInstall + ''; + meta = { + description = "Node.js ${version}, the official nodejs.org build"; + homepage = "https://nodejs.org"; + license = lib.licenses.mit; + mainProgram = "node"; + platforms = builtins.attrNames builds; + }; +} From 2f0a5c43119b6c0fb3e830e419846c2d24b67505 Mon Sep 17 00:00:00 2001 From: "M.Hoffmann" Date: Thu, 22 Oct 2026 04:28:53 -0300 Subject: [PATCH 2/2] ci: cve scan on main, on pull requests and every Monday cve.yml has two jobs. osv runs OSV-Scanner over every lock file in the repository against osv.dev. node runs is-my-node-vulnerable on the node of labs/gleam-website against Node.js's own advisories. The workflow runs on push to main, so an advisory published after a merge still turns main red, and every Monday at 06:17 UTC. labs/ptbr-pdf/osv-scanner.toml lists the 8 advisories in that lab's Cargo.lock that the lab cannot fix: 2 in quick-xml 0.38.4 (RUSTSEC-2026-0194 and -0195, fixed in 0.41.0, which comes in through typst's citationberg and plist), and 6 unmaintained crates with no known flaw (bincode, paste, rustybuzz, ttf-parser, unsafe-libyaml, yaml-rust). Each entry has its reason and ignoreUntil 2027-01-22, so the scan fails again on that date. The owner asked for this workflow by name ("CVE scan no GitHub Actions" for h0ffmann/picasso), as AGENTS.md requires for a change to .github/workflows/. Tested: nix run nixpkgs#osv-scanner -- scan source -r . (No issues found, 8 filtered with their reasons); nix run nixpkgs#actionlint (exit 0); nix run nixpkgs#reuse -- lint (compliant, 388/388); is-my-node-vulnerable@1.6.1 on node 24.22.1 (exit 0) Co-Authored-By: Claude --- .github/workflows/cve.yml | 41 +++++++++++++++++++++++++++++++ labs/ptbr-pdf/osv-scanner.toml | 44 ++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 .github/workflows/cve.yml create mode 100644 labs/ptbr-pdf/osv-scanner.toml diff --git a/.github/workflows/cve.yml b/.github/workflows/cve.yml new file mode 100644 index 0000000..fec7b8c --- /dev/null +++ b/.github/workflows/cve.yml @@ -0,0 +1,41 @@ +# cve: known vulnerabilities in what this repository pins. Runs on main after each merge, on each +# pull request, and every Monday, so an advisory published after a merge still turns main red. +# +# - osv: OSV-Scanner reads every lock file (the labs' Cargo.lock, package-lock.json) against +# osv.dev. An advisory with no fix the lab can take is listed, with its reason and an expiry +# date, in that lab's osv-scanner.toml. +# - node: is-my-node-vulnerable checks the Node that labs/gleam-website gives against Node.js's own +# advisories (nodejs/security-wg). Those advisories lag the Node.js blog, so the lab also states +# its minimum Node in checks.node-version, which ci.yml builds. +name: cve + +on: + push: + branches: [main] + pull_request: + schedule: + - cron: "17 6 * * 1" + workflow_dispatch: + +permissions: + contents: read + +jobs: + osv: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v7 + - uses: DeterminateSystems/nix-installer-action@v23 + - name: OSV-Scanner over every lock file + run: nix run nixpkgs#osv-scanner -- scan source --recursive . + + node: + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v7 + - uses: DeterminateSystems/nix-installer-action@v23 + - name: is-my-node-vulnerable, on the Node of labs/gleam-website + working-directory: labs/gleam-website + run: nix develop --no-update-lock-file --command bash -c 'node --version && npx --yes is-my-node-vulnerable@1.6.1' diff --git a/labs/ptbr-pdf/osv-scanner.toml b/labs/ptbr-pdf/osv-scanner.toml new file mode 100644 index 0000000..6f041e2 --- /dev/null +++ b/labs/ptbr-pdf/osv-scanner.toml @@ -0,0 +1,44 @@ +# OSV-Scanner exceptions for this lab's Cargo.lock (.github/workflows/cve.yml). Each entry is an +# advisory that has no fix this lab can take: the crate comes in through typst, and only a typst +# update moves it. ignoreUntil makes the scan fail again on that date, so each one is read again. +# Read from api.osv.dev on 2026-10-22. + +[[IgnoredVulns]] +id = "RUSTSEC-2026-0194" +ignoreUntil = 2027-01-22T00:00:00Z +reason = "quick-xml 0.38.4, quadratic time on duplicate attributes. It comes from typst's citationberg and plist; the lock already has 0.42.0 for the rest. Whether to-pdf ever hands it untrusted XML was not checked. Fixed in 0.41.0: drop this when typst updates." + +[[IgnoredVulns]] +id = "RUSTSEC-2026-0195" +ignoreUntil = 2027-01-22T00:00:00Z +reason = "quick-xml 0.38.4, unbounded namespace allocation in NsReader. Same path and same fix as RUSTSEC-2026-0194." + +[[IgnoredVulns]] +id = "RUSTSEC-2025-0141" +ignoreUntil = 2027-01-22T00:00:00Z +reason = "bincode is unmaintained (no known flaw); it comes from typst's dependencies." + +[[IgnoredVulns]] +id = "RUSTSEC-2024-0436" +ignoreUntil = 2027-01-22T00:00:00Z +reason = "paste is unmaintained (no known flaw); it comes from typst's dependencies." + +[[IgnoredVulns]] +id = "RUSTSEC-2026-0206" +ignoreUntil = 2027-01-22T00:00:00Z +reason = "rustybuzz is unmaintained (no known flaw); typst's text shaping." + +[[IgnoredVulns]] +id = "RUSTSEC-2026-0192" +ignoreUntil = 2027-01-22T00:00:00Z +reason = "ttf-parser is unmaintained (no known flaw); typst's font parsing, of the six embedded fonts." + +[[IgnoredVulns]] +id = "RUSTSEC-2024-0449" +ignoreUntil = 2027-01-22T00:00:00Z +reason = "unsafe-libyaml is unmaintained (no known flaw); it comes from typst's dependencies." + +[[IgnoredVulns]] +id = "RUSTSEC-2024-0320" +ignoreUntil = 2027-01-22T00:00:00Z +reason = "yaml-rust is unmaintained (no known flaw); it comes from typst's dependencies."