hackerone-client 0.15.0 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +28 -12
- data/.rubocop.yml +4 -0
- data/CHANGELOG.md +21 -0
- data/Gemfile +11 -3
- data/Guardfile +2 -0
- data/README.md +8 -2
- data/Rakefile +10 -1
- data/bin/console +1 -0
- data/fixtures/vcr_cassettes/create_report.yml +81 -0
- data/fixtures/vcr_cassettes/create_report_invalid.yml +79 -0
- data/fixtures/vcr_cassettes/lock_report.yml +156 -0
- data/fixtures/vcr_cassettes/report.yml +22 -1
- data/fixtures/vcr_cassettes/report_list_triaged.yml +77 -0
- data/fixtures/vcr_cassettes/update_severity.yml +78 -0
- data/hackerone-client.gemspec +4 -2
- data/lib/hackerone/client.rb +56 -9
- data/lib/hackerone/client/activity.rb +20 -8
- data/lib/hackerone/client/address.rb +2 -0
- data/lib/hackerone/client/attachment.rb +24 -0
- data/lib/hackerone/client/bounty.rb +2 -0
- data/lib/hackerone/client/group.rb +2 -0
- data/lib/hackerone/client/incremental/activities.rb +3 -1
- data/lib/hackerone/client/member.rb +2 -0
- data/lib/hackerone/client/program.rb +4 -2
- data/lib/hackerone/client/report.rb +63 -5
- data/lib/hackerone/client/reporter.rb +2 -0
- data/lib/hackerone/client/resource_helper.rb +5 -3
- data/lib/hackerone/client/structured_scope.rb +2 -0
- data/lib/hackerone/client/swag.rb +2 -0
- data/lib/hackerone/client/user.rb +2 -0
- data/lib/hackerone/client/version.rb +3 -1
- data/lib/hackerone/client/weakness.rb +16 -14
- metadata +9 -2
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./resource_helper"
|
2
4
|
|
3
5
|
module HackerOne
|
4
6
|
module Client
|
@@ -71,7 +73,7 @@ module HackerOne
|
|
71
73
|
"programs/#{id}/swag",
|
72
74
|
params: { page: { number: page_number, size: page_size } }
|
73
75
|
)
|
74
|
-
response_body.map{|r| Swag.new(r, self) }
|
76
|
+
response_body.map { |r| Swag.new(r, self) }
|
75
77
|
end
|
76
78
|
|
77
79
|
private
|
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./resource_helper"
|
4
|
+
require_relative "./weakness"
|
5
|
+
require_relative "./activity"
|
4
6
|
|
5
7
|
module HackerOne
|
6
8
|
module Client
|
@@ -24,6 +26,22 @@ module HackerOne
|
|
24
26
|
duplicate
|
25
27
|
).map(&:to_sym).freeze
|
26
28
|
|
29
|
+
RESOLVED_STATES = %w(
|
30
|
+
resolved
|
31
|
+
not-applicable
|
32
|
+
informative
|
33
|
+
duplicate
|
34
|
+
spam
|
35
|
+
).map(&:to_sym).freeze
|
36
|
+
|
37
|
+
SEVERITY_RATINGS = %w(
|
38
|
+
none
|
39
|
+
low
|
40
|
+
medium
|
41
|
+
high
|
42
|
+
critical
|
43
|
+
).freeze
|
44
|
+
|
27
45
|
class << self
|
28
46
|
def add_on_state_change_hook(proc)
|
29
47
|
on_state_change_hooks << proc
|
@@ -62,6 +80,10 @@ module HackerOne
|
|
62
80
|
attributes[:issue_tracker_reference_id]
|
63
81
|
end
|
64
82
|
|
83
|
+
def severity
|
84
|
+
attributes[:severity]
|
85
|
+
end
|
86
|
+
|
65
87
|
def state
|
66
88
|
attributes[:state]
|
67
89
|
end
|
@@ -118,7 +140,13 @@ module HackerOne
|
|
118
140
|
|
119
141
|
# Bounty writeups just use the key, and not the label value.
|
120
142
|
def writeup_classification
|
121
|
-
classification_label
|
143
|
+
classification_label.split("-").first
|
144
|
+
end
|
145
|
+
|
146
|
+
def attachments
|
147
|
+
@attachments ||= relationships.fetch(:attachments, {})
|
148
|
+
.fetch(:data, [])
|
149
|
+
.map { |attachment| HackerOne::Client::Attachment.new(attachment) }
|
122
150
|
end
|
123
151
|
|
124
152
|
def activities
|
@@ -159,6 +187,23 @@ module HackerOne
|
|
159
187
|
Swag.new(response_body, program)
|
160
188
|
end
|
161
189
|
|
190
|
+
def update_severity(rating:)
|
191
|
+
raise ArgumentError, "Invalid severity rating" unless SEVERITY_RATINGS.include?(rating.to_s)
|
192
|
+
|
193
|
+
request_body = {
|
194
|
+
type: "severity",
|
195
|
+
attributes: {
|
196
|
+
rating: rating
|
197
|
+
}
|
198
|
+
}
|
199
|
+
response_body = make_post_request(
|
200
|
+
"reports/#{id}/severities",
|
201
|
+
request_body: request_body
|
202
|
+
)
|
203
|
+
@report[:attributes][:severity] = { rating: rating }
|
204
|
+
Activities.build(response_body)
|
205
|
+
end
|
206
|
+
|
162
207
|
def suggest_bounty(message:, amount:, bonus_amount: nil)
|
163
208
|
request_body = {
|
164
209
|
message: message,
|
@@ -261,6 +306,19 @@ module HackerOne
|
|
261
306
|
HackerOne::Client::Activities.build(response_json)
|
262
307
|
end
|
263
308
|
|
309
|
+
def lock!
|
310
|
+
unless RESOLVED_STATES.include? self.state.to_sym
|
311
|
+
raise ArgumentError, "Report must be closed before locking"
|
312
|
+
end
|
313
|
+
|
314
|
+
body = {
|
315
|
+
type: "activity-comments-closed"
|
316
|
+
}
|
317
|
+
|
318
|
+
response_json = make_put_request("reports/#{id}/close_comments", request_body: body)
|
319
|
+
HackerOne::Client::Activities.build(response_json)
|
320
|
+
end
|
321
|
+
|
264
322
|
def assign_to_user(name)
|
265
323
|
member = program.find_member(name)
|
266
324
|
_assign_to(member.user.id, :user)
|
@@ -304,7 +362,7 @@ module HackerOne
|
|
304
362
|
request_body[:id] = assignee_id if assignee_id
|
305
363
|
|
306
364
|
response = HackerOne::Client::Api.hackerone_api_connection.put do |req|
|
307
|
-
req.headers[
|
365
|
+
req.headers["Content-Type"] = "application/json"
|
308
366
|
req.url "reports/#{id}/assignee"
|
309
367
|
req.body = { data: request_body }.to_json
|
310
368
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HackerOne
|
2
4
|
module Client
|
3
5
|
module ResourceHelper
|
@@ -14,7 +16,7 @@ module HackerOne
|
|
14
16
|
|
15
17
|
def make_put_request(url, request_body:, extract_data: true)
|
16
18
|
response = HackerOne::Client::Api.hackerone_api_connection.put do |req|
|
17
|
-
req.headers[
|
19
|
+
req.headers["Content-Type"] = "application/json"
|
18
20
|
req.url url
|
19
21
|
req.body = { data: request_body }.to_json
|
20
22
|
end
|
@@ -24,7 +26,7 @@ module HackerOne
|
|
24
26
|
|
25
27
|
def make_post_request(url, request_body:, extract_data: true)
|
26
28
|
response = HackerOne::Client::Api.hackerone_api_connection.post do |req|
|
27
|
-
req.headers[
|
29
|
+
req.headers["Content-Type"] = "application/json"
|
28
30
|
req.url url
|
29
31
|
req.body = { data: request_body }.to_json
|
30
32
|
end
|
@@ -34,7 +36,7 @@ module HackerOne
|
|
34
36
|
|
35
37
|
def make_get_request(url, params: {}, extract_data: true)
|
36
38
|
response = HackerOne::Client::Api.hackerone_api_connection.get do |req|
|
37
|
-
req.headers[
|
39
|
+
req.headers["Content-Type"] = "application/json"
|
38
40
|
req.url url
|
39
41
|
req.params = params
|
40
42
|
end
|
@@ -1,17 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HackerOne
|
2
4
|
module Client
|
3
5
|
class Weakness
|
4
6
|
class << self
|
5
7
|
def validate_cwe!(cwe)
|
6
|
-
fail NotAnOwaspWeaknessError if cwe.upcase.start_with?(
|
7
|
-
fail StandardError::ArgumentError unless cwe.upcase.start_with?(
|
8
|
+
fail NotAnOwaspWeaknessError if cwe.upcase.start_with?("CAPEC-")
|
9
|
+
fail StandardError::ArgumentError unless cwe.upcase.start_with?("CWE-")
|
8
10
|
end
|
9
11
|
|
10
12
|
def extract_cwe_number(cwe)
|
11
13
|
return if cwe.nil?
|
12
14
|
validate_cwe!(cwe)
|
13
15
|
|
14
|
-
cwe.split(
|
16
|
+
cwe.split("CWE-").last.to_i
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
@@ -39,20 +41,20 @@ module HackerOne
|
|
39
41
|
}
|
40
42
|
|
41
43
|
OWASP_TOP_10_2013_TO_CWE = {
|
42
|
-
|
43
|
-
|
44
|
+
"A1-Injection" => [77, 78, 88, 89, 90, 91, 564],
|
45
|
+
"A2-AuthSession" =>
|
44
46
|
[287, 613, 522, 256, 384, 472, 346, 441, 523, 620, 640, 319, 311],
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
"A3-XSS" => [79],
|
48
|
+
"A4-DirectObjRef" => [639, 99, 22],
|
49
|
+
"A5-Misconfig" => [16, 2, 215, 548, 209],
|
50
|
+
"A6-DataExposure" => [312, 319, 310, 326, 320, 311, 325, 328, 327],
|
51
|
+
"A7-MissingACL" => [285, 287],
|
52
|
+
"A8-CSRF" => [352, 642, 613, 346, 441],
|
53
|
+
"A9-KnownVuln" => [],
|
54
|
+
"A10-Redirects" => [601],
|
53
55
|
}.freeze
|
54
56
|
|
55
|
-
OWASP_DEFAULT =
|
57
|
+
OWASP_DEFAULT = "A0-Other".freeze
|
56
58
|
|
57
59
|
def initialize(weakness)
|
58
60
|
@attributes = weakness
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hackerone-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil Matatall
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- ".github/workflows/build.yml"
|
119
119
|
- ".gitignore"
|
120
120
|
- ".rspec"
|
121
|
+
- ".rubocop.yml"
|
121
122
|
- ".travis.yml"
|
122
123
|
- CHANGELOG.md
|
123
124
|
- CODE_OF_CONDUCT.md
|
@@ -141,12 +142,16 @@ files:
|
|
141
142
|
- fixtures/vcr_cassettes/award_a_bounty.yml
|
142
143
|
- fixtures/vcr_cassettes/award_swag.yml
|
143
144
|
- fixtures/vcr_cassettes/common_responses.yml
|
145
|
+
- fixtures/vcr_cassettes/create_report.yml
|
146
|
+
- fixtures/vcr_cassettes/create_report_invalid.yml
|
144
147
|
- fixtures/vcr_cassettes/dup.yml
|
145
148
|
- fixtures/vcr_cassettes/empty_report_list.yml
|
149
|
+
- fixtures/vcr_cassettes/lock_report.yml
|
146
150
|
- fixtures/vcr_cassettes/missing_report.yml
|
147
151
|
- fixtures/vcr_cassettes/programs.yml
|
148
152
|
- fixtures/vcr_cassettes/report.yml
|
149
153
|
- fixtures/vcr_cassettes/report_list.yml
|
154
|
+
- fixtures/vcr_cassettes/report_list_triaged.yml
|
150
155
|
- fixtures/vcr_cassettes/reporters.yml
|
151
156
|
- fixtures/vcr_cassettes/server_error.yml
|
152
157
|
- fixtures/vcr_cassettes/server_error_when_assigning_report_to_user.yml
|
@@ -158,11 +163,13 @@ files:
|
|
158
163
|
- fixtures/vcr_cassettes/traverse_through_all_activities.yml
|
159
164
|
- fixtures/vcr_cassettes/triage_and_hook_assign_report_to_user.yml
|
160
165
|
- fixtures/vcr_cassettes/update_policy.yml
|
166
|
+
- fixtures/vcr_cassettes/update_severity.yml
|
161
167
|
- fixtures/vcr_cassettes/user_find_fransrosen.yml
|
162
168
|
- hackerone-client.gemspec
|
163
169
|
- lib/hackerone/client.rb
|
164
170
|
- lib/hackerone/client/activity.rb
|
165
171
|
- lib/hackerone/client/address.rb
|
172
|
+
- lib/hackerone/client/attachment.rb
|
166
173
|
- lib/hackerone/client/bounty.rb
|
167
174
|
- lib/hackerone/client/group.rb
|
168
175
|
- lib/hackerone/client/incremental/activities.rb
|