Skip to content

Commit 8344e3c

Browse files
committed
address potential weaknesses
1 parent 163b3f2 commit 8344e3c

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

lib/join_code_generator.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
# frozen_string_literal: true
22

3+
require 'securerandom'
4+
35
class JoinCodeGenerator
46
# Omit K, X, Z — commonly confused or offensive in short codes.
57
CONSONANTS = %w[B C D F G H J L M N P Q R S T V W Y].freeze
68

79
# Format: CDDD-CDDD (e.g., B123-C456). C = consonant from CONSONANTS, D = digit.
810
FORMAT_REGEX = Regexp.new("\\A(?:#{CONSONANTS.join('|')})\\d{3}-(?:#{CONSONANTS.join('|')})\\d{3}\\z").freeze
911

10-
cattr_accessor :random
11-
12-
self.random ||= Random.new
13-
1412
def self.generate
1513
seg = lambda do
16-
"#{CONSONANTS.sample(random: random)}#{format('%03d', random.rand(1000))}"
14+
consonant = CONSONANTS[SecureRandom.random_number(CONSONANTS.length)]
15+
"#{consonant}#{format('%03d', SecureRandom.random_number(1000))}"
1716
end
1817

1918
"#{seg.call}-#{seg.call}"

spec/lib/join_code_generator_spec.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
it 'matches CDDD-CDDD' do
88
expect(described_class.generate).to match(described_class::FORMAT_REGEX)
99
end
10+
11+
it 'uses SecureRandom for each code component' do
12+
allow(SecureRandom).to receive(:random_number).with(described_class::CONSONANTS.length).and_return(0, 1)
13+
allow(SecureRandom).to receive(:random_number).with(1000).and_return(123, 456)
14+
15+
expect(described_class.generate).to eq('B123-C456')
16+
expect(SecureRandom).to have_received(:random_number).with(described_class::CONSONANTS.length).twice
17+
expect(SecureRandom).to have_received(:random_number).with(1000).twice
18+
end
1019
end
1120

1221
describe '.normalize' do

0 commit comments

Comments
 (0)