logo

cve-client

CLI-based client / toolbox for CVE.org
commit: 616a9461c63ffe064ede64adaf8b1e14781e2da7
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat,  2 Oct 2021 20:46:50 +0200

Initial Commit

Diffstat:

Acve-client.pl105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+), 0 deletions(-)

diff --git a/cve-client.pl b/cve-client.pl @@ -0,0 +1,105 @@ +#!/usr/bin/env perl +# CVE-Client: CLI-based client / toolbox for CVE.org +# Copyright © 2021 CVE-Client Authors <https://hacktivis.me/git/cve-client/> +# SPDX-License-Identifier: AGPL-3.0-only +use strict; +use utf8; +no warnings; # Wide Character… + +use Getopt::Std; +use LWP::UserAgent; +use JSON::MaybeXS; + +my $json = JSON::MaybeXS->new(utf8 => 1); + +my %options=(); + +sub usage { + print "usage: ap-fetch.pl [-r|-j] <CVE-ID>\n"; + print " -r Raw output\n"; + print " -j Pipe into jq(1)\n"; + print "Otherwise it tries to do a plain-text representation.\n"; + exit 1; +} + +sub print_cve { + my ($object, $cve_id) = @_; + + + print "CVE ID: ", $cve_id, "\n\n"; + + if($object->{'data_version'} != "4.0") { + print "Warning: Got unknown CVE format \"", $object->{'data_version'}, "\"\n"; + } + + if($object->{'CVE_data_meta'}->{'ID'} != $cve_id) { + print "Warning: Got ", $object->{'CVE_data_meta'}->{'ID'}, " instead of ", $cve_id, "\n"; + } + + if($object->{'description'}->{'description_data'}) { + my $descs = $object->{'description'}->{'description_data'}; + + foreach(@{$descs}) { + print "Description Language: ", $_->{'lang'}, "\n"; + print "Description: «\n", $_->{'value'}, "\n»\n"; + } + } else { + print "Warning: No CVE description could be found!"; + } + + if($object->{'references'}->{'reference_data'}) { + my $refs = $object->{'references'}->{'reference_data'}; + + foreach(@{$refs}) { + print "Reference Source: ", $_->{'refsource'}, "\n"; + print "- Name: ", $_->{'name'}, "\n" if $_->{'name'}; + print "- URL: ", $_->{'url'}, "\n" if $_->{'url'}; + print "\n" + } + } else { + print "Warning: No CVE references could be found!"; + } +} + +sub fetch_cve { + my ($cve_id) = @_; + my $url = 'https://www.cve.org/api/?action=getCveById&cveId='.$cve_id; + #print "Fetching: ", $url, "\n"; + my $ua = LWP::UserAgent->new; + $ua->agent("CVE-Client fetch <https://hacktivis.me/git/cve-client/>"); + my $req = HTTP::Request->new(GET => $url); + #$req->header('Accept' => 'application/json'); + + my $res = $ua->request($req); + + if($res->is_success) { + my $content_type = $res->header("Content-Type"); + my $content_match = 'application/json'; + + if($content_type == $content_match) { + if(defined $options{r}) { + print $res->content; + } elsif(defined $options{j}) { + open(my $pipe_out, '|-', 'jq .') or die "Couldn't open a pipe into jq: $!"; + print $pipe_out $res->content; + } else { + my $object = $json->decode($res->content); + print_cve($object, $cve_id); + } + } else { + print "Got $content_type instead of $content_match"; + } + } else { + print "Got ", $res->status_line, " instead of 2xx\n"; + } +} + +getopts("rj", \%options); + +if($#ARGV != 0) { usage; } + +if($ARGV[0] =~ /^CVE-\d{4}-\d+$/) { + fetch_cve($ARGV[0]); +} else { + usage(); +}