cve-client.pl (3204B)
- #!/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 " -g Gemtext format\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->{'error'} and $object->{'message'}) {
- print "Error (", $object->{'error'}, "): ", $object->{'message'}, "\n";
- exit 1;
- }
- 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}) {
- if (defined $options{g}) {
- print "Reference Source: ", $_->{'refsource'}, "\n";
- print "=> ", $_->{'url'} if $_->{'url'};
- if ($_->{'name'}) {
- print " ", $_->{'name'}, "\n\n";
- } else {
- print "\n\n";
- }
- } else {
- 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("rjg", \%options);
- if ($#ARGV != 0) { usage; }
- if ($ARGV[0] =~ /^CVE-\d{4}-\d+$/) {
- fetch_cve($ARGV[0]);
- } else {
- usage();
- }