File Coverage

blib/lib/App/CveClient.pm
Criterion Covered Total %
statement 48 98 48.9
branch 8 44 18.1
condition 1 3 33.3
subroutine 5 6 83.3
pod 0 3 0.0
total 62 154 40.2


line stmt bran cond sub pod time code
1             # CVE-Client: CLI-based client / toolbox for CVE.org
2             # Copyright © 2021-2023 CVE-Client Authors
3             # SPDX-License-Identifier: AGPL-3.0-only
4             package App::CveClient;
5             our $VERSION = 'v1.0.5';
6              
7 1     1   111876 use warnings;
  1         2  
  1         32  
8 1     1   6 use strict;
  1         1  
  1         22  
9              
10 1     1   5 use Exporter qw(import);
  1         9  
  1         1174  
11              
12             our @EXPORT_OK = qw(print_cve print_cve50 print_cve40);
13              
14             sub print_cve {
15 2     2 0 4054 my ($object, $cve_id, $format) = @_;
16              
17 2         85 print "CVE ID: ", $cve_id, "\n";
18              
19 2 0 33     13 if ($object->{'error'} and $object->{'message'}) {
20 0         0 die "Error ($object->{'error'}): $object->{'message'}\n";
21             }
22              
23 2 50       10 if ($object->{'dataVersion'} == "5.0") {
    0          
24 2         7 print_cve50($object, $cve_id, $format);
25             } elsif ($object->{'data_version'} == "4.0") {
26 0         0 print_cve40($object, $cve_id, $format);
27             } else {
28 0         0 print STDERR "Error: unknown CVE format:\n";
29             print STDERR "- data_version: ", $object->{'data_version'}, "\n"
30 0 0       0 if $object->{'data_version'};
31             print STDERR "- dataVersion: ", $object->{'dataVersion'}, "\n"
32 0 0       0 if $object->{'dataVersion'};
33             }
34             }
35              
36             # https://github.com/CVEProject/cve-schema/blob/master/schema/v5.0/
37             sub print_cve50 {
38 2     2 0 5 my ($object, $cve_id, $format) = @_;
39              
40 2 100       6 if ($object->{'cveMetadata'}->{'cveId'} ne $cve_id) {
41 1         22 print STDERR "Warning: Got <", $object->{'cveMetadata'}->{'cveId'},
42             "> instead of <", $cve_id, ">\n";
43             }
44              
45 2         6 my $affected = $object->{'containers'}->{'cna'}->{'affected'};
46 2 50       5 if ($affected) {
47 2         4 foreach (@{$affected}) {
  2         4  
48 2         26 print "Vendor Name: ", $_->{'vendor'}, "\n"; # vendor required
49 2         22 print "Product Name: ", $_->{'product'}, "\n"; # product required
50              
51 2         6 foreach (@{$_->{'versions'}}) {
  2         5  
52 2         22 print "- ", $_->{'status'}, ": ", $_->{'version'}, "\n";
53             }
54             }
55             } else {
56 0         0 print STDERR
57             "Warning: No CVE affected versions could be found! (as required by the spec)\n";
58             }
59              
60 2         21 print "\n";
61              
62 2         6 my $metrics = $object->{'containers'}->{'cna'}->{'metrics'};
63 2 50       5 if ($metrics) {
64 2         3 foreach (@{$metrics}) {
  2         4  
65 2 50       5 if ($_->{'cvssV3_1'}) {
66 2         2 my $metric = $_->{'cvssV3_1'};
67             print "- Score: ", $metric->{'baseScore'}, " ",
68 2         37 $metric->{'baseSeverity'}, "\n";
69             } else {
70 0         0 print "Notice: unhandled metrics (CVSS) data\n";
71             }
72             }
73             } else {
74 0         0 print STDERR
75             "Warning: No CVE metrics (CVSS) could be found! (as required by the spec)\n";
76             }
77              
78 2         21 print "\n";
79              
80 2         7 my $desc = $object->{'containers'}->{'cna'}->{'descriptions'};
81 2 50       5 if ($desc) {
82 2         3 foreach (@{$desc}) {
  2         4  
83 2         19 print "Description Language: ", $_->{'lang'}, "\n";
84 2         30 print "Description:\n", $_->{'value'}, "\n\n";
85             }
86             } else {
87 0         0 print STDERR
88             "Warning: No CVE description could be found! (as required by the spec)\n";
89             }
90              
91 2         21 print "\n";
92              
93 2         7 my $refs = $object->{'containers'}->{'cna'}->{'references'};
94 2 50       12 if ($refs) {
95 2         30 print "References: \n";
96              
97 2         6 foreach (@{$refs}) {
  2         5  
98 12         134 print "=> ", $_->{'url'}, "\n";
99             }
100             } else {
101 0           print STDERR
102             "Warning: No CVE references could be found! (as required by the spec)\n";
103             }
104             }
105              
106             # https://github.com/CVEProject/cve-schema/blob/master/schema/v4.0/
107             sub print_cve40 {
108 0     0 0   my ($object, $cve_id, $format) = @_;
109              
110 0 0         if ($object->{'CVE_data_meta'}->{'ID'} ne $cve_id) {
111 0           print STDERR "Warning: Got ", $object->{'CVE_data_meta'}->{'ID'},
112             " instead of ", $cve_id, "\n";
113             }
114              
115             print "TITLE: ", $object->{'CVE_data_meta'}->{'TITLE'}, "\n"
116 0 0         if $object->{'CVE_data_meta'}->{'TITLE'};
117              
118 0           print "\n";
119              
120 0 0         if ($object->{'affects'}->{'vendor'}) {
121 0           foreach (@{$object->{'affects'}->{'vendor'}->{'vendor_data'}}) {
  0            
122             print "Vendor Name: ", $_->{'vendor_name'}, "\n"
123 0 0         if $_->{'vendor_name'};
124              
125 0           foreach (@{$_->{'product'}->{'product_data'}}) {
  0            
126 0           print "Product name: ", $_->{'product_name'}, "\n";
127 0           print "Product versions: ";
128              
129 0           foreach (@{$_->{'version'}->{'version_data'}}) {
  0            
130 0           print $_->{'version_value'}, "; ";
131             }
132              
133 0           print "\n";
134             }
135             }
136             }
137              
138 0           print "\n";
139              
140 0 0         if ($object->{'description'}->{'description_data'}) {
141 0           my $descs = $object->{'description'}->{'description_data'};
142              
143 0           foreach (@{$descs}) {
  0            
144 0           print "Description Language: ", $_->{'lang'}, "\n";
145 0           print "Description:\n", $_->{'value'}, "\n\n";
146             }
147             } else {
148 0           print STDERR "Warning: No CVE description could be found!\n";
149             }
150              
151 0 0         if ($object->{'references'}->{'reference_data'}) {
152 0           my $refs = $object->{'references'}->{'reference_data'};
153              
154 0           foreach (@{$refs}) {
  0            
155 0 0         if ($format == 'gemini') {
156 0           print "Reference Source: ", $_->{'refsource'}, "\n";
157              
158 0 0         print "=> ", $_->{'url'} if $_->{'url'};
159 0 0         if ($_->{'name'}) {
160 0           print " ", $_->{'name'}, "\n\n";
161             } else {
162 0           print "\n\n";
163             }
164             } else {
165 0           print "Reference Source: ", $_->{'refsource'}, "\n";
166 0 0         print "- Name: ", $_->{'name'}, "\n" if $_->{'name'};
167 0 0         print "- URL: ", $_->{'url'}, "\n" if $_->{'url'};
168 0           print "\n";
169             }
170             }
171             } else {
172 0           print STDERR "Warning: No CVE references could be found!\n";
173             }
174             }
175              
176             1;