From 8344e3c51fcc8f9f8023ad1bc914be968ed04f21 Mon Sep 17 00:00:00 2001 From: abcampo-iry <261805581+abcampo-iry@users.noreply.github.com> Date: Thu, 6 Aug 2026 12:49:17 +0200 Subject: [PATCH] address potential weaknesses --- lib/join_code_generator.rb | 9 ++++----- spec/lib/join_code_generator_spec.rb | 9 +++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/join_code_generator.rb b/lib/join_code_generator.rb index 84a1005a2..0e4f89f53 100644 --- a/lib/join_code_generator.rb +++ b/lib/join_code_generator.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'securerandom' + class JoinCodeGenerator # Omit K, X, Z — commonly confused or offensive in short codes. CONSONANTS = %w[B C D F G H J L M N P Q R S T V W Y].freeze @@ -7,13 +9,10 @@ class JoinCodeGenerator # Format: CDDD-CDDD (e.g., B123-C456). C = consonant from CONSONANTS, D = digit. FORMAT_REGEX = Regexp.new("\\A(?:#{CONSONANTS.join('|')})\\d{3}-(?:#{CONSONANTS.join('|')})\\d{3}\\z").freeze - cattr_accessor :random - - self.random ||= Random.new - def self.generate seg = lambda do - "#{CONSONANTS.sample(random: random)}#{format('%03d', random.rand(1000))}" + consonant = CONSONANTS[SecureRandom.random_number(CONSONANTS.length)] + "#{consonant}#{format('%03d', SecureRandom.random_number(1000))}" end "#{seg.call}-#{seg.call}" diff --git a/spec/lib/join_code_generator_spec.rb b/spec/lib/join_code_generator_spec.rb index 5cd1b0999..100d318ee 100644 --- a/spec/lib/join_code_generator_spec.rb +++ b/spec/lib/join_code_generator_spec.rb @@ -7,6 +7,15 @@ it 'matches CDDD-CDDD' do expect(described_class.generate).to match(described_class::FORMAT_REGEX) end + + it 'uses SecureRandom for each code component' do + allow(SecureRandom).to receive(:random_number).with(described_class::CONSONANTS.length).and_return(0, 1) + allow(SecureRandom).to receive(:random_number).with(1000).and_return(123, 456) + + expect(described_class.generate).to eq('B123-C456') + expect(SecureRandom).to have_received(:random_number).with(described_class::CONSONANTS.length).twice + expect(SecureRandom).to have_received(:random_number).with(1000).twice + end end describe '.normalize' do