From 9afd1386470c3c10365ebffe72e361a16475ecbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AA=E3=81=A4=E3=81=8D?= Date: Fri, 9 Jan 2026 16:13:25 -0800 Subject: [PATCH 1/4] Add restriction and validation for download urls --- .github/workflows/test.yml | 11 +++++++++++ generate-windows-versions.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a15c2b56d..9783dc117 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -369,6 +369,17 @@ jobs: - name: C:/msys64/mingw64/bin/gcc.exe not installed run: ruby -e "abort if File.exist?('C:/msys64/mingw64/bin/gcc.exe')" + validate-windows-versions: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: ./ + with: + ruby-version: ruby + - run: ruby generate-windows-versions.rb + - name: Check generated files are up to date + run: git diff --exit-code + lint: runs-on: ubuntu-22.04 steps: diff --git a/generate-windows-versions.rb b/generate-windows-versions.rb index 6fb1fd26d..08b2625c6 100644 --- a/generate-windows-versions.rb +++ b/generate-windows-versions.rb @@ -2,6 +2,31 @@ require 'yaml' require 'json' +# General rules: +# - All the static parts of the expected URL are checked literally. +# - Don't forget to escape dot (`.`) and other special characters when used literally. +# - Each path component must begin with [\w], or a more restrictive character set. +# - Percent (`%`) shall not be allowed to avoid any percent encoding. +WINDOWS_VERSIONS_URLS_REGEXPS = [ + %r{^https://github\.com/oneclick/rubyinstaller2?/releases/download/\w[\w.-]*/\w[\w.-]*$}, + %r{^https://github\.com/MSP-Greg/ruby-loco/releases/download/\w[\w.-]*/\w[\w.-]*$} +].freeze + +WINDOWS_TOOLCHAIN_VERSIONS_URLS_REGEXPS = [ + %r{^https://github\.com/oneclick/rubyinstaller/releases/download/devkit-4\.7\.2/DevKit-mingw64-64-4\.7\.2-20130224-1432-sfx\.exe$}, + %r{^https://github\.com/ruby/setup-msys2-gcc/releases/download/\w[\w.-]*/\w[\w@.-]*$}, + %r{^https://github\.com/ruby/setup-msys2-gcc/releases/latest/download/\w[\w@.-]*$} +].freeze + +# Validate all the URLs in the versions json +def validate(versions, allowed_urls_regexps) + versions.values.flat_map(&:values).each do |url| + if allowed_urls_regexps.none? { |regexp| regexp =~ url } + raise SecurityError, "Unexpected URL: #{url}" + end + end +end + min_requirements = ['~> 2.0.0', '~> 2.1.9', '>= 2.2.6'].map { |req| Gem::Requirement.new(req) } url = 'https://raw.githubusercontent.com/oneclick/rubyinstaller.org-website/master/_data/downloads.yaml' @@ -48,6 +73,7 @@ 'x64' => 'https://github.com/MSP-Greg/ruby-loco/releases/download/ruby-master/ruby-ucrt.7z' } +validate(versions, WINDOWS_VERSIONS_URLS_REGEXPS) File.binwrite 'windows-versions.json', "#{JSON.pretty_generate(versions)}\n" base_url = 'https://github.com/ruby/setup-msys2-gcc/releases/latest/download/windows-toolchain.json' @@ -90,4 +116,5 @@ end end +validate(versions, WINDOWS_TOOLCHAIN_VERSIONS_URLS_REGEXPS) File.binwrite 'windows-toolchain-versions.json', "#{JSON.pretty_generate(versions)}\n" From 47db116e529544bec4da716fc4e34e2addeef28b Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 13 Jan 2026 10:54:56 +0100 Subject: [PATCH 2/4] Match more strictly with \A and \z --- generate-windows-versions.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/generate-windows-versions.rb b/generate-windows-versions.rb index 08b2625c6..1969701ed 100644 --- a/generate-windows-versions.rb +++ b/generate-windows-versions.rb @@ -8,20 +8,20 @@ # - Each path component must begin with [\w], or a more restrictive character set. # - Percent (`%`) shall not be allowed to avoid any percent encoding. WINDOWS_VERSIONS_URLS_REGEXPS = [ - %r{^https://github\.com/oneclick/rubyinstaller2?/releases/download/\w[\w.-]*/\w[\w.-]*$}, - %r{^https://github\.com/MSP-Greg/ruby-loco/releases/download/\w[\w.-]*/\w[\w.-]*$} + %r{\Ahttps://github\.com/oneclick/rubyinstaller2?/releases/download/\w[\w.-]*/\w[\w.-]*\z}, + %r{\Ahttps://github\.com/MSP-Greg/ruby-loco/releases/download/\w[\w.-]*/\w[\w.-]*\z} ].freeze WINDOWS_TOOLCHAIN_VERSIONS_URLS_REGEXPS = [ - %r{^https://github\.com/oneclick/rubyinstaller/releases/download/devkit-4\.7\.2/DevKit-mingw64-64-4\.7\.2-20130224-1432-sfx\.exe$}, - %r{^https://github\.com/ruby/setup-msys2-gcc/releases/download/\w[\w.-]*/\w[\w@.-]*$}, - %r{^https://github\.com/ruby/setup-msys2-gcc/releases/latest/download/\w[\w@.-]*$} + %r{\Ahttps://github\.com/oneclick/rubyinstaller/releases/download/devkit-4\.7\.2/DevKit-mingw64-64-4\.7\.2-20130224-1432-sfx\.exe\z}, + %r{\Ahttps://github\.com/ruby/setup-msys2-gcc/releases/download/\w[\w.-]*/\w[\w@.-]*\z}, + %r{\Ahttps://github\.com/ruby/setup-msys2-gcc/releases/latest/download/\w[\w@.-]*\z} ].freeze # Validate all the URLs in the versions json def validate(versions, allowed_urls_regexps) versions.values.flat_map(&:values).each do |url| - if allowed_urls_regexps.none? { |regexp| regexp =~ url } + if allowed_urls_regexps.none? { |regexp| regexp.match? url } raise SecurityError, "Unexpected URL: #{url}" end end From daffe6ad255752878ce7ffa1cd070c8d43faffaf Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 13 Jan 2026 10:59:42 +0100 Subject: [PATCH 3/4] Use Regexp.escape to not need to manually escape (error-prone) --- generate-windows-versions.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/generate-windows-versions.rb b/generate-windows-versions.rb index 1969701ed..ab885ffdf 100644 --- a/generate-windows-versions.rb +++ b/generate-windows-versions.rb @@ -4,18 +4,18 @@ # General rules: # - All the static parts of the expected URL are checked literally. -# - Don't forget to escape dot (`.`) and other special characters when used literally. # - Each path component must begin with [\w], or a more restrictive character set. # - Percent (`%`) shall not be allowed to avoid any percent encoding. WINDOWS_VERSIONS_URLS_REGEXPS = [ - %r{\Ahttps://github\.com/oneclick/rubyinstaller2?/releases/download/\w[\w.-]*/\w[\w.-]*\z}, - %r{\Ahttps://github\.com/MSP-Greg/ruby-loco/releases/download/\w[\w.-]*/\w[\w.-]*\z} + %r{\A#{Regexp.escape 'https://github.com/oneclick/rubyinstaller/releases/download'}/\w[\w.-]*/\w[\w.-]*\z}, + %r{\A#{Regexp.escape 'https://github.com/oneclick/rubyinstaller2/releases/download'}/\w[\w.-]*/\w[\w.-]*\z}, + %r{\A#{Regexp.escape 'https://github.com/MSP-Greg/ruby-loco/releases/download'}/\w[\w.-]*/\w[\w.-]*\z} ].freeze WINDOWS_TOOLCHAIN_VERSIONS_URLS_REGEXPS = [ - %r{\Ahttps://github\.com/oneclick/rubyinstaller/releases/download/devkit-4\.7\.2/DevKit-mingw64-64-4\.7\.2-20130224-1432-sfx\.exe\z}, - %r{\Ahttps://github\.com/ruby/setup-msys2-gcc/releases/download/\w[\w.-]*/\w[\w@.-]*\z}, - %r{\Ahttps://github\.com/ruby/setup-msys2-gcc/releases/latest/download/\w[\w@.-]*\z} + %r{\A#{Regexp.escape 'https://github.com/oneclick/rubyinstaller/releases/download/devkit-4.7.2/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe'}\z}, + %r{\A#{Regexp.escape 'https://github.com/ruby/setup-msys2-gcc/releases/download'}/\w[\w.-]*/\w[\w@.-]*\z}, + %r{\A#{Regexp.escape 'https://github.com/ruby/setup-msys2-gcc/releases/latest/download'}/\w[\w@.-]*\z} ].freeze # Validate all the URLs in the versions json From 4148b4328b8bcd1abbe863254a37001116745bfd Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 13 Jan 2026 11:02:37 +0100 Subject: [PATCH 4/4] Give a proper name to CI jobs checking generated files --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9783dc117..87916a0a1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -370,6 +370,7 @@ jobs: run: ruby -e "abort if File.exist?('C:/msys64/mingw64/bin/gcc.exe')" validate-windows-versions: + name: "Check windows*versions.json are up-to-date" runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 @@ -380,7 +381,8 @@ jobs: - name: Check generated files are up to date run: git diff --exit-code - lint: + check-dist-index: + name: "Check dist/index.js is up-to-date" runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v6