fluent-plugin-jfrog-siem 2.0.8 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d54b989518483df9f5df0a16bf1911fd57a0c2768e3bb7eeadfe566f023a0a54
4
- data.tar.gz: fb9ebc429c302d9f3ae1b1003e32277f8fe6d49c490b316da5300f2b91346265
3
+ metadata.gz: 74c423ae40c052a7a8f53ff8f8d744ffcaa2032553f9c331866fdc1b186ce076
4
+ data.tar.gz: e7e096bda67598350f0502f91f0602542d616fb0406dfa1f1274a7b82ab0f0e0
5
5
  SHA512:
6
- metadata.gz: d7be078791c0d2a802b7cbda86e3af7489147b70b1f36ae757b400b3c014fcfb61de2e1539b448010c3e95c71ae643c2c74184416a2a0f94f6be6ab29d370a6f
7
- data.tar.gz: ee1a8bb8716fdd04bb96e11aa4b0f85965835e080a5d9f5524b694584f72c0635e3e1069f71250d868207e9cf54aefe820ed8bf3085994c434f6b066eadc8268
6
+ metadata.gz: ecc3e648b0a7f9d68262e0aed5a403c3c3ebc7ab345234f7156997079c37a3ed5548a33cac35f80be129bfd5cfae665672ed64db58ed197b2340af61a702d099
7
+ data.tar.gz: cc261ed12d53934671349002785cb037b064a4abac399bf7dca783568a4586da8dcb4c9d665e6cd885654aca0a6fe1f51a7f3aaaffbba04f6627a53bb0115d45
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-plugin-jfrog-siem (2.0.8)
4
+ fluent-plugin-jfrog-siem (2.0.9)
5
5
  concurrent-ruby-edge
6
6
  fluentd (>= 0.14.10, < 2)
7
7
  rest-client (~> 2.0)
@@ -86,6 +86,7 @@ GEM
86
86
  PLATFORMS
87
87
  arm64-darwin-23
88
88
  x86_64-darwin-20
89
+ x86_64-linux
89
90
 
90
91
  DEPENDENCIES
91
92
  bundler (~> 2.0)
@@ -97,4 +98,4 @@ DEPENDENCIES
97
98
  test-unit (~> 3.0)
98
99
 
99
100
  BUNDLED WITH
100
- 2.2.3
101
+ 2.4.19
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "fluent-plugin-jfrog-siem"
6
- spec.version = "2.0.8"
6
+ spec.version = "2.0.9"
7
7
  spec.authors = ["Mahitha Byreddy", "Ben Harosh"]
8
8
  spec.email = ["partner-support@jfrog.com"]
9
9
 
@@ -90,6 +90,7 @@ class Xray
90
90
  cve = []
91
91
  cvss_v2_list = []
92
92
  cvss_v3_list = []
93
+ cvss_v4_list = []
93
94
  policy_list = []
94
95
  rule_list = []
95
96
  impacted_artifact_url_list = []
@@ -105,20 +106,32 @@ class Xray
105
106
  if properties[index].key?('cvss_v3')
106
107
  cvss_v3_list.push(properties[index]['cvss_v3'])
107
108
  end
109
+ if properties[index].key?('cvss_v4')
110
+ cvss_v4_list.push(properties[index]['cvss_v4'])
111
+ end
108
112
  end
109
113
 
110
114
  detailResp_json["cve"] = cve.sort.reverse[0]
111
115
  cvss_v2 = cvss_v2_list.sort.reverse[0]
112
116
  cvss_v3 = cvss_v3_list.sort.reverse[0]
117
+ cvss_v4 = cvss_v4_list.sort.reverse[0]
118
+ # cvss_v4 is only a fallback so the reported score doesn't change for violations that also have v3/v2
113
119
  if !cvss_v3.nil?
114
120
  cvss = cvss_v3
115
121
  elsif !cvss_v2.nil?
116
122
  cvss = cvss_v2
123
+ elsif !cvss_v4.nil?
124
+ cvss = cvss_v4
125
+ end
126
+ if !cvss.nil?
127
+ cvss_score = cvss[0..2]
128
+ detailResp_json["cvss_score"] = cvss_score
129
+ # A score without a vector (e.g. "2.4") has no ':' to take the version from
130
+ cvss_version_part = cvss.split(':')[1]
131
+ if !cvss_version_part.nil?
132
+ detailResp_json["cvss_version"] = cvss_version_part[0..2]
133
+ end
117
134
  end
118
- cvss_score = cvss[0..2]
119
- cvss_version = cvss.split(':')[1][0..2]
120
- detailResp_json["cvss_score"] = cvss_score
121
- detailResp_json["cvss_version"] = cvss_version
122
135
  end
123
136
 
124
137
  if detailResp_json.key?('matched_policies')
@@ -135,7 +148,7 @@ class Xray
135
148
  detailResp_json['rules'] = rule_list
136
149
  end
137
150
 
138
- detailResp_json['impacted_artifacts'].each do |impacted_artifact|
151
+ (detailResp_json['impacted_artifacts'] || []).each do |impacted_artifact|
139
152
  matchdata = impacted_artifact.match /default\/(?<repo_name>[^\/]*)\/(?<path>.*)/
140
153
  if matchdata
141
154
  impacted_artifact_url = matchdata['repo_name'] + ":" + matchdata['path'] + " "
@@ -0,0 +1,300 @@
1
+ # spec/data_normalization_spec.rb
2
+ #
3
+ # Tests for Xray#data_normalization covering JOBS-2850:
4
+ # When violation properties lack cvss_v2 / cvss_v3 (e.g. Security violations
5
+ # for issues with no CVSS score, or only a CVSS v4 score) the method must NOT
6
+ # raise NoMethodError on `cvss[0..2]`.
7
+ #
8
+ # Expected results before the fix:
9
+ # - Violations without CVSS v2/v3 data → FAIL (demonstrates the bug)
10
+ # - CVSS score without a vector → FAIL
11
+ # - Missing impacted_artifacts → FAIL
12
+ # - Security-with-CVSS v2/v3 tests → PASS (existing logic is correct)
13
+
14
+ [
15
+ File.join(File.dirname(__FILE__), '..'),
16
+ File.join(File.dirname(__FILE__), '..', 'lib/fluent/plugin'),
17
+ File.join(File.dirname(__FILE__), '..', 'spec'),
18
+ ].each do |dir|
19
+ $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
20
+ end
21
+
22
+ require 'spec_helper'
23
+
24
+ RSpec.describe Xray, '#data_normalization' do
25
+ # Build an Xray instance with all dummy/nil params — we only need the method.
26
+ # Constructor signature: (jpd_url, username, api_key, token, wait_interval,
27
+ # batch_size, pos_file_path, router, tag)
28
+ subject(:xray) do
29
+ Xray.new(nil, nil, nil, nil, nil, nil, nil, nil, nil)
30
+ end
31
+
32
+ # ─────────────────────────────────────────────────────────────────────────
33
+ # JOBS-2850: License violation — properties have no cvss_v2 / cvss_v3
34
+ # ─────────────────────────────────────────────────────────────────────────
35
+ describe 'License violation without CVSS data' do
36
+ let(:license_violation) do
37
+ {
38
+ 'issue_id' => 'Apache-2.0',
39
+ 'type' => 'License',
40
+ 'properties' => [{ 'license' => 'Apache-2.0' }],
41
+ 'impacted_artifacts' => ['default/maven-repo-1/com/example/foo/bar.jar']
42
+ }
43
+ end
44
+
45
+ it 'does not raise an error (regression for JOBS-2850)' do
46
+ # BUG: cvss is nil → cvss[0..2] raises NoMethodError undefined method '[]' for nil
47
+ expect { xray.data_normalization(license_violation) }.not_to raise_error
48
+ end
49
+
50
+ it 'returns a Hash' do
51
+ result = xray.data_normalization(license_violation)
52
+ expect(result).to be_a(Hash)
53
+ end
54
+
55
+ it 'does not set cvss_score when CVSS data is absent' do
56
+ result = xray.data_normalization(license_violation)
57
+ expect(result).not_to have_key('cvss_score')
58
+ end
59
+
60
+ it 'does not set cvss_version when CVSS data is absent' do
61
+ result = xray.data_normalization(license_violation)
62
+ expect(result).not_to have_key('cvss_version')
63
+ end
64
+ end
65
+
66
+ # ─────────────────────────────────────────────────────────────────────────
67
+ # JOBS-2850: Operational Risk violation — properties have no cvss_v2 / cvss_v3
68
+ # ─────────────────────────────────────────────────────────────────────────
69
+ describe 'Operational Risk violation without CVSS data' do
70
+ let(:op_risk_violation) do
71
+ {
72
+ 'issue_id' => 'EOL-component-1234',
73
+ 'type' => 'Operational Risk',
74
+ 'properties' => [{ 'end_of_life' => 'true' }],
75
+ 'impacted_artifacts' => ['default/npm-repo/lodash/-/lodash-4.0.0.tgz']
76
+ }
77
+ end
78
+
79
+ it 'does not raise an error (regression for JOBS-2850)' do
80
+ # BUG: same as License — cvss stays nil, cvss[0..2] crashes
81
+ expect { xray.data_normalization(op_risk_violation) }.not_to raise_error
82
+ end
83
+
84
+ it 'returns a Hash' do
85
+ result = xray.data_normalization(op_risk_violation)
86
+ expect(result).to be_a(Hash)
87
+ end
88
+
89
+ it 'does not set cvss_score when CVSS data is absent' do
90
+ result = xray.data_normalization(op_risk_violation)
91
+ expect(result).not_to have_key('cvss_score')
92
+ end
93
+
94
+ it 'does not set cvss_version when CVSS data is absent' do
95
+ result = xray.data_normalization(op_risk_violation)
96
+ expect(result).not_to have_key('cvss_version')
97
+ end
98
+ end
99
+
100
+ # ─────────────────────────────────────────────────────────────────────────
101
+ # JOBS-2850: Security violation with a CVE but no CVSS data at all
102
+ # ─────────────────────────────────────────────────────────────────────────
103
+ describe 'Security violation with a CVE but without CVSS data' do
104
+ let(:security_violation_no_cvss) do
105
+ {
106
+ 'issue_id' => 'SIEMTEST-NOCVSS-1',
107
+ 'type' => 'Security',
108
+ 'properties' => [{ 'cve' => 'CVE-2099-28500' }],
109
+ 'impacted_artifacts' => ['default/npm-siem-test/siem-mit-pkg/-/siem-mit-pkg-1.0.0.tgz']
110
+ }
111
+ end
112
+
113
+ it 'does not raise an error (regression for JOBS-2850)' do
114
+ expect { xray.data_normalization(security_violation_no_cvss) }.not_to raise_error
115
+ end
116
+
117
+ it 'still sets the cve' do
118
+ result = xray.data_normalization(security_violation_no_cvss)
119
+ expect(result['cve']).to eq('CVE-2099-28500')
120
+ end
121
+
122
+ it 'does not set cvss_score or cvss_version' do
123
+ result = xray.data_normalization(security_violation_no_cvss)
124
+ expect(result).not_to have_key('cvss_score')
125
+ expect(result).not_to have_key('cvss_version')
126
+ end
127
+ end
128
+
129
+ # ─────────────────────────────────────────────────────────────────────────
130
+ # JOBS-2850: Security violation with only a CVSS v4 score
131
+ # ─────────────────────────────────────────────────────────────────────────
132
+ describe 'Security violation with only CVSS v4 data' do
133
+ let(:security_violation_v4) do
134
+ {
135
+ 'issue_id' => 'XRAY-1073490',
136
+ 'type' => 'Security',
137
+ 'properties' => [
138
+ {
139
+ 'cve' => 'CVE-2026-84445',
140
+ 'cwe' => ['CWE-129', 'CWE-248'],
141
+ 'cvss_v4' => '8.7/CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N'
142
+ }
143
+ ],
144
+ 'impacted_artifacts' => ['default/build-info/some-build']
145
+ }
146
+ end
147
+
148
+ it 'does not raise an error (regression for JOBS-2850)' do
149
+ expect { xray.data_normalization(security_violation_v4) }.not_to raise_error
150
+ end
151
+
152
+ it 'sets cvss_score from cvss_v4' do
153
+ result = xray.data_normalization(security_violation_v4)
154
+ expect(result['cvss_score']).to eq('8.7')
155
+ end
156
+
157
+ it 'sets cvss_version from cvss_v4' do
158
+ result = xray.data_normalization(security_violation_v4)
159
+ expect(result['cvss_version']).to eq('4.0')
160
+ end
161
+ end
162
+
163
+ # ─────────────────────────────────────────────────────────────────────────
164
+ # Security violation with both CVSS v3 and v4 — v3 is kept
165
+ # ─────────────────────────────────────────────────────────────────────────
166
+ describe 'Security violation with both CVSS v3 and v4 (v3 kept)' do
167
+ let(:security_violation_v3_v4) do
168
+ {
169
+ 'issue_id' => 'CVE-2024-5678',
170
+ 'type' => 'Security',
171
+ 'properties' => [
172
+ {
173
+ 'cve' => 'CVE-2024-5678',
174
+ 'cvss_v3' => '7.5/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H',
175
+ 'cvss_v4' => '8.7/CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N'
176
+ }
177
+ ],
178
+ 'impacted_artifacts' => ['default/maven-repo/some-lib/1.0/some-lib-1.0.jar']
179
+ }
180
+ end
181
+
182
+ it 'uses cvss_v3, not cvss_v4' do
183
+ result = xray.data_normalization(security_violation_v3_v4)
184
+ expect(result['cvss_score']).to eq('7.5')
185
+ expect(result['cvss_version']).to eq('3.1')
186
+ end
187
+ end
188
+
189
+ # ─────────────────────────────────────────────────────────────────────────
190
+ # Security violation with a CVSS score but no vector (e.g. custom issues)
191
+ # ─────────────────────────────────────────────────────────────────────────
192
+ describe 'Security violation with a CVSS score but no vector' do
193
+ let(:security_violation_score_only) do
194
+ {
195
+ 'issue_id' => 'CUSTOM-ISSUE-1',
196
+ 'type' => 'Security',
197
+ 'properties' => [{ 'cve' => 'CVE-2017-1000386', 'cvss_v2' => '2.4' }],
198
+ 'impacted_artifacts' => ['default/maven-repo/aero/aero/0.2.3/aero-0.2.3.jar']
199
+ }
200
+ end
201
+
202
+ it 'does not raise an error' do
203
+ expect { xray.data_normalization(security_violation_score_only) }.not_to raise_error
204
+ end
205
+
206
+ it 'sets cvss_score' do
207
+ result = xray.data_normalization(security_violation_score_only)
208
+ expect(result['cvss_score']).to eq('2.4')
209
+ end
210
+
211
+ it 'does not set cvss_version' do
212
+ result = xray.data_normalization(security_violation_score_only)
213
+ expect(result).not_to have_key('cvss_version')
214
+ end
215
+ end
216
+
217
+ # ─────────────────────────────────────────────────────────────────────────
218
+ # Violation without impacted_artifacts (key absent or null)
219
+ # ─────────────────────────────────────────────────────────────────────────
220
+ describe 'Violation without impacted_artifacts' do
221
+ it 'does not raise an error when the key is absent' do
222
+ violation = { 'issue_id' => 'CVE-2099-28500', 'type' => 'Security', 'properties' => [{ 'cve' => 'CVE-2099-28500' }] }
223
+ expect { xray.data_normalization(violation) }.not_to raise_error
224
+ end
225
+
226
+ it 'sets an empty impacted_artifacts_url when the value is null' do
227
+ violation = { 'issue_id' => 'CVE-2099-28500', 'type' => 'Security', 'impacted_artifacts' => nil }
228
+ result = xray.data_normalization(violation)
229
+ expect(result['impacted_artifacts_url']).to eq([])
230
+ end
231
+ end
232
+
233
+ # ─────────────────────────────────────────────────────────────────────────
234
+ # Security violation WITH CVSS v3 only (existing behaviour must keep working)
235
+ # ─────────────────────────────────────────────────────────────────────────
236
+ describe 'Security violation with CVSS v3 data' do
237
+ let(:security_violation_v3) do
238
+ {
239
+ 'issue_id' => 'CVE-2021-44228',
240
+ 'type' => 'Security',
241
+ 'properties' => [
242
+ {
243
+ 'cve' => 'CVE-2021-44228',
244
+ 'cvss_v3' => '9.8/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'
245
+ }
246
+ ],
247
+ 'impacted_artifacts' => ['default/maven-repo/log4j/core/2.14.1/log4j-core-2.14.1.jar']
248
+ }
249
+ end
250
+
251
+ it 'does not raise an error' do
252
+ expect { xray.data_normalization(security_violation_v3) }.not_to raise_error
253
+ end
254
+
255
+ it 'sets cvss_score to the leading numeric score (e.g. "9.8")' do
256
+ result = xray.data_normalization(security_violation_v3)
257
+ expect(result['cvss_score']).to eq('9.8')
258
+ end
259
+
260
+ it 'sets cvss_version to the CVSS major.minor version (e.g. "3.1")' do
261
+ result = xray.data_normalization(security_violation_v3)
262
+ expect(result['cvss_version']).to eq('3.1')
263
+ end
264
+ end
265
+
266
+ # ─────────────────────────────────────────────────────────────────────────
267
+ # Security violation WITH both CVSS v2 AND v3 — v3 must be preferred
268
+ # ─────────────────────────────────────────────────────────────────────────
269
+ describe 'Security violation with both CVSS v2 and v3 (v3 preferred)' do
270
+ let(:security_violation_both) do
271
+ {
272
+ 'issue_id' => 'CVE-2020-1234',
273
+ 'type' => 'Security',
274
+ 'properties' => [
275
+ {
276
+ 'cve' => 'CVE-2020-1234',
277
+ 'cvss_v2' => '7.5/AV:N/AC:L/Au:N/C:P/I:P/A:P',
278
+ 'cvss_v3' => '9.8/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'
279
+ }
280
+ ],
281
+ 'impacted_artifacts' => ['default/maven-repo/some-lib/1.0/some-lib-1.0.jar']
282
+ }
283
+ end
284
+
285
+ it 'does not raise an error' do
286
+ expect { xray.data_normalization(security_violation_both) }.not_to raise_error
287
+ end
288
+
289
+ it 'uses cvss_v3 score (not cvss_v2) when both are present' do
290
+ result = xray.data_normalization(security_violation_both)
291
+ # v3 score is 9.8; v2 score is 7.5 — the result must reflect v3
292
+ expect(result['cvss_score']).to eq('9.8')
293
+ end
294
+
295
+ it 'sets cvss_version from cvss_v3 when both are present' do
296
+ result = xray.data_normalization(security_violation_both)
297
+ expect(result['cvss_version']).to eq('3.1')
298
+ end
299
+ end
300
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-jfrog-siem
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.8
4
+ version: 2.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mahitha Byreddy
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-11-07 00:00:00.000000000 Z
12
+ date: 2026-10-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -163,7 +163,7 @@ files:
163
163
  - lib/fluent/plugin/test_violations.rb
164
164
  - lib/fluent/plugin/violations.json
165
165
  - lib/fluent/plugin/xray.rb
166
- - pkg/fluent-plugin-jfrog-siem-2.0.8.gem
166
+ - spec/data_normalization_spec.rb
167
167
  - spec/position_file_spec.rb
168
168
  - spec/spec_helper.rb
169
169
  - spec/xray_spec.rb
@@ -188,12 +188,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
188
  - !ruby/object:Gem::Version
189
189
  version: '0'
190
190
  requirements: []
191
- rubygems_version: 3.5.3
191
+ rubygems_version: 3.4.19
192
192
  signing_key:
193
193
  specification_version: 4
194
194
  summary: JFrog SIEM fluent input plugin will send the SIEM events from JFrog Xray
195
195
  to Fluentd
196
196
  test_files:
197
+ - spec/data_normalization_spec.rb
197
198
  - spec/position_file_spec.rb
198
199
  - spec/spec_helper.rb
199
200
  - spec/xray_spec.rb
Binary file