Skip to content

Commit d720dc0

Browse files
committed
Add support for insecure sources
1 parent f96c1c2 commit d720dc0

File tree

9 files changed

+462
-20
lines changed

9 files changed

+462
-20
lines changed

lib/cc/engine/bundler_audit.rb

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
require "versionomy"
44

55
require "cc/engine/bundler_audit/analyzer"
6-
require "cc/engine/bundler_audit/issue"
7-
require "cc/engine/bundler_audit/remediation"
6+
require "cc/engine/bundler_audit/insecure_source_issue"
7+
require "cc/engine/bundler_audit/unpatched_gem_issue"
8+
require "cc/engine/bundler_audit/unpatched_gem_remediation"
89

910
module CC
1011
module Engine

lib/cc/engine/bundler_audit/analyzer.rb

+11-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def run
1313
if gemfile_lock_exists?
1414
Dir.chdir(directory) do
1515
Bundler::Audit::Scanner.new.scan do |vulnerability|
16-
issue = Issue.new(vulnerability, gemfile_lock_lines)
16+
issue = issue_for_vulerability(vulnerability)
1717

1818
io.print("#{issue.to_json}\0")
1919
end
@@ -27,8 +27,17 @@ def run
2727

2828
attr_reader :directory, :io
2929

30+
def issue_for_vulerability(vulnerability)
31+
case vulnerability
32+
when Bundler::Audit::Scanner::UnpatchedGem
33+
UnpatchedGemIssue.new(vulnerability, gemfile_lock_lines)
34+
when Bundler::Audit::Scanner::InsecureSource
35+
InsecureSourceIssue.new(vulnerability, gemfile_lock_lines)
36+
end
37+
end
38+
3039
def gemfile_lock_lines
31-
@gemfile_lock_lines ||= File.open(gemfile_lock_path).lines.to_a
40+
@gemfile_lock_lines ||= File.open(gemfile_lock_path).each_line.to_a
3241
end
3342

3443
def gemfile_lock_exists?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module CC
2+
module Engine
3+
module BundlerAudit
4+
class InsecureSourceIssue
5+
REMEDIATION_POINTS = 5_000_000
6+
SOURCE_REGEX = /^\s*remote: (?<source>\S+)/
7+
8+
def initialize(result, gemfile_lock_lines)
9+
@source = result.source
10+
@gemfile_lock_lines = gemfile_lock_lines
11+
end
12+
13+
def to_json(*a)
14+
{
15+
categories: %w[Security],
16+
check_name: "Insecure Source",
17+
content: {
18+
body: "",
19+
},
20+
description: "Insecure Source URI found: #{source}",
21+
location: {
22+
path: "Gemfile.lock",
23+
lines: {
24+
begin: line_number,
25+
end: line_number,
26+
},
27+
},
28+
remediation_points: REMEDIATION_POINTS,
29+
severity: "normal",
30+
type: "Issue",
31+
}.to_json(a)
32+
end
33+
34+
private
35+
36+
attr_reader :source, :gemfile_lock_lines
37+
38+
def line_number
39+
@line_number ||= begin
40+
gemfile_lock_lines.find_index do |line|
41+
(match = SOURCE_REGEX.match(line)) && match[:source] == source
42+
end + 1
43+
end
44+
end
45+
end
46+
end
47+
end
48+
end

lib/cc/engine/bundler_audit/issue.rb renamed to lib/cc/engine/bundler_audit/unpatched_gem_issue.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module CC
22
module Engine
33
module BundlerAudit
4-
class Issue
4+
class UnpatchedGemIssue
55
GEM_REGEX = /^\s*(?<name>\S+) \([\d.]+\)/
66
SEVERITIES = {
77
high: "critical",
@@ -63,7 +63,7 @@ def remediation_points
6363
requirements.last
6464
end
6565

66-
Remediation.new(gem.version, patched_versions).points
66+
UnpatchedGemRemediation.new(gem.version, patched_versions).points
6767
end
6868

6969
def severity

lib/cc/engine/bundler_audit/remediation.rb renamed to lib/cc/engine/bundler_audit/unpatched_gem_remediation.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module CC
22
module Engine
33
module BundlerAudit
4-
class Remediation
4+
class UnpatchedGemRemediation
55
MAJOR_UPGRADE_POINTS = 50_000_000
66
MINOR_UPGRADE_POINTS = 5_000_000
77
PATCH_UPGRADE_POINTS = 500_000

spec/cc/engine/bundler_audit/analyzer_spec.rb

+17-4
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,29 @@ module CC::Engine::BundlerAudit
1111
to raise_error(Analyzer::GemfileLockNotFound)
1212
end
1313

14-
it "emits issues for Gemfile.lock problems" do
14+
it "emits issues for unpatched gems in Gemfile.lock" do
1515
io = StringIO.new
1616
directory = fixture_directory("unpatched_versions")
1717

18+
issues = analyze_directory(directory, io)
19+
20+
expect(issues).to eq(expected_issues("unpatched_versions"))
21+
end
22+
23+
it "emits issues for insecure sources in Gemfile.lock" do
24+
io = StringIO.new
25+
directory = fixture_directory("insecure_source")
26+
27+
issues = analyze_directory(directory, io)
28+
29+
expect(issues).to eq(expected_issues("insecure_source"))
30+
end
31+
32+
def analyze_directory(directory, io)
1833
audit = Analyzer.new(directory: directory, io: io)
1934
audit.run
2035

21-
issues = io.string.split("\0").map { |issue| JSON.load(issue) }
22-
23-
expect(issues).to eq(expected_issues("unpatched_versions"))
36+
io.string.split("\0").map { |issue| JSON.load(issue) }
2437
end
2538

2639
def expected_issues(fixture)

spec/cc/engine/bundler_audit/remediation_spec.rb

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
require "spec_helper"
22

33
module CC::Engine::BundlerAudit
4-
describe Remediation do
4+
describe UnpatchedGemRemediation do
55
describe "#points" do
66
it "returns major upgrade remediation points when an upgrade requies a major version bump" do
7-
remediation = Remediation.new("1.0.0", %w[2.0.1 3.0.1])
7+
remediation = UnpatchedGemRemediation.new("1.0.0", %w[2.0.1 3.0.1])
88

9-
expect(remediation.points).to eq(Remediation::MAJOR_UPGRADE_POINTS)
9+
expect(remediation.points).to eq(UnpatchedGemRemediation::MAJOR_UPGRADE_POINTS)
1010
end
1111

1212
it "returns minor upgrade remediation points when an upgrade requies a minor version bump" do
13-
remediation = Remediation.new("1.0.0", %w[1.2.1 2.2.1])
13+
remediation = UnpatchedGemRemediation.new("1.0.0", %w[1.2.1 2.2.1])
1414

15-
expect(remediation.points).to eq(Remediation::MINOR_UPGRADE_POINTS)
15+
expect(remediation.points).to eq(UnpatchedGemRemediation::MINOR_UPGRADE_POINTS)
1616
end
1717

1818
it "returns patch upgrade remediation points when an upgrade requies a patch version bump" do
19-
remediation = Remediation.new("1.0.0", %w[1.0.3 2.0.3])
19+
remediation = UnpatchedGemRemediation.new("1.0.0", %w[1.0.3 2.0.3])
2020

21-
expect(remediation.points).to eq(Remediation::PATCH_UPGRADE_POINTS)
21+
expect(remediation.points).to eq(UnpatchedGemRemediation::PATCH_UPGRADE_POINTS)
2222
end
2323

2424
it "returns unpatched version remediation points when an upgrade is not possible" do
25-
remediation = Remediation.new("1.0.0", [])
25+
remediation = UnpatchedGemRemediation.new("1.0.0", [])
2626

27-
expect(remediation.points).to eq(Remediation::UNPATCHED_VERSION_POINTS)
27+
expect(remediation.points).to eq(UnpatchedGemRemediation::UNPATCHED_VERSION_POINTS)
2828
end
2929
end
3030
end

0 commit comments

Comments
 (0)