Skip to content

Commit

Permalink
Merge f12abdd into e801617
Browse files Browse the repository at this point in the history
  • Loading branch information
alxberardi committed Dec 21, 2016
2 parents e801617 + f12abdd commit df4b23d
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 76 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This changelog adheres to [Keep a CHANGELOG](http://keepachangelog.com/).
### Fixed
- Implements stricter credit cards pattern matching
- Matches unconventionally formatted credit cards
- Scans every sub string for credit cards

## [0.2.1] - 2016-12-19
### Changed
Expand Down
24 changes: 6 additions & 18 deletions lib/sensitive_data_filter/types/credit_card.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,11 @@
module SensitiveDataFilter
module Types
module CreditCard
SEPARATORS = /[\s-]/
SEPRS = SEPARATORS.source + '+'
CARD_16_DIGITS = /\d{4}#{SEPRS}\d{4}#{SEPRS}\d{4}#{SEPRS}\d{4}/
CARD_13_DIGITS = /\d{3}#{SEPRS}\d{3}#{SEPRS}\d{3}#{SEPRS}\d#{SEPRS}\d{3}/
CARD_14_DIGITS = /\d{4}#{SEPRS}\d{6}#{SEPRS}\d{4}/
CARD_15_DIGITS = /\d{4}#{SEPRS}\d{6}#{SEPRS}\d{5}/
CARD = /
#{CARD_16_DIGITS.source}
| #{CARD_13_DIGITS.source}
| #{CARD_14_DIGITS.source}
| #{CARD_15_DIGITS.source}
/x
CATCH_ALL_SEPRS = SEPARATORS.source + '*'
CATCH_ALL = /(?:\d#{CATCH_ALL_SEPRS}?){13,16}/
FILTERED = '[FILTERED]'
SEPARATORS = /[\s-]/
SEPRS = SEPARATORS.source + '*'
LENGTHS = (11..19)
CARD = Regexp.new(LENGTHS.map { |l| /(?=((?:\d#{SEPRS}){#{l - 1}}\d)?)/.source }.join)
FILTERED = '[FILTERED]'

module_function def valid?(number)
return false unless number.is_a? String
Expand All @@ -27,9 +17,7 @@ module CreditCard

module_function def scan(value)
return [] unless value.is_a? String
[CARD, CATCH_ALL]
.flat_map { |pattern| value.scan(pattern) }.uniq
.select { |card| valid?(card) }
value.scan(CARD).flatten.compact.select { |card| valid?(card) }
end

module_function def mask(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
specify { expect(parser.unparse('test' => true)).to eq parameters }

context 'when parsing raises exceptions' do
specify { expect{parser.parse('not json')}.not_to raise_error }
specify { expect { parser.parse('not json') }.not_to raise_error }
specify { expect(parser.parse('not json')).to eq 'not json' }

let(:nan) { 0.0/0 }
specify { expect{parser.unparse(nan)}.not_to raise_error }
let(:nan) { 0.0 / 0 }
specify { expect { parser.unparse(nan) }.not_to raise_error }
specify { expect(parser.unparse(nan)).to be nan }
end
end
Expand Down
72 changes: 17 additions & 55 deletions spec/sensitive_data_filter/types/credit_card_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,30 @@ def validations(cards)

context 'a value that contains valid credit card numbers in a longer numerical pattern' do
let(:value) { '1234111 1111 1111 1111234' }
specify { expect(scan).to eq ['4111 1111 1111 1111'] }
specify { expect(scan).to eq ['34111 1111 1111 11', '4111 1111 1111 1111'] }
end

context 'a value that contains repeated valid credit card numbers' do
let(:value) { 'cc1 4111 1111 1111 1111 cc2 4111 1111 1111 1111 123' }
specify { expect(scan).to eq ['4111 1111 1111 1111'] }
specify { expect(scan).to eq ['4111 1111 1111 1111', '4111 1111 1111 1111'] }
end

context 'a value that contains valid credit cards in a multi line string' do
let(:value) { '@TEST\n3782 822463 10005\nEXP: 07/20\n' }
context 'a value that contains a valid credit card in a multi line string' do
let(:value) { "@TEST\n3782 822463 10005\nEXP: 07/20\n" }
specify { expect(scan).to eq ['3782 822463 10005'] }
specify { expect(mask).to eq '@TEST\n[FILTERED]\nEXP: 07/20\n' }
specify { expect(mask).to eq "@TEST\n[FILTERED]\nEXP: 07/20\n" }
end

context 'a value that contains a valid tab separated credit card on multiple lines' do
let(:value) { "@TEST\n3782\t822463\n10005\nEXP: 07/20\n" }
specify { expect(scan).to eq ["3782\t822463\n10005"] }
specify { expect(mask).to eq "@TEST\n[FILTERED]\nEXP: 07/20\n" }
end

context 'a value that is a luhn but not a credit card' do
let(:value) { '1230-2675-9183-4267' }
specify { expect(scan).to be_empty }
specify { expect(mask).to eq value }
end

context 'a value that does not contain valid credit card numbers' do
Expand All @@ -94,55 +106,5 @@ def validations(cards)
specify { expect(scan).to be_empty }
specify { expect(mask).to eq value }
end

context 'a value that is a luhn but not a credit card' do
let(:value) { '1234-5678-9012-3528' }
specify { expect(scan).to be_empty }
specify { expect(mask).to eq value }
end
end

describe 'pattern matching' do
shared_examples_for 'a pattern matcher' do
context 'valid pattern' do
it 'should match' do
expect(subject.match(valid_match)[0]).to eq valid_match
end
end

context 'invalid pattern' do
it 'should not match' do
expect(subject.match(invalid_match)).to be_nil
end
end
end

context '13 digit card pattern' do
subject { SensitiveDataFilter::Types::CreditCard::CARD_13_DIGITS }
let(:valid_match) { '123-123-123-1-123' }
let(:invalid_match) { '1234-123-123-1-35' }
it_behaves_like 'a pattern matcher'
end

context '14 digit card pattern' do
subject { SensitiveDataFilter::Types::CreditCard::CARD_14_DIGITS }
let(:valid_match) { '1234-123456-1234' }
let(:invalid_match) { '1234-12345-123' }
it_behaves_like 'a pattern matcher'
end

context '15 digit card' do
subject { SensitiveDataFilter::Types::CreditCard::CARD_15_DIGITS }
let(:valid_match) { '1234-123456-12345' }
let(:invalid_match) { '123-1234567-12345' }
it_behaves_like 'a pattern matcher'
end

context '16 digit card pattern' do
subject(:card_16_digits) { SensitiveDataFilter::Types::CreditCard::CARD_16_DIGITS }
let(:valid_match) { '1234-5678-9012-3528' }
let(:invalid_match) { '1234-15678-012-3528' }
it_behaves_like 'a pattern matcher'
end
end
end

0 comments on commit df4b23d

Please sign in to comment.