The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Net::NVD - query CVE data from NIST's NVD (National Vulnerability Database)

SYNOPSIS

    use Net::NVD;

    my $nvd = Net::NVD->new;

    # query a specific CVE
    my $cve = $nvd->get( 'CVE-2019-1010218' );
    say $cve->{descriptions}[0]{value};

    # get non-rejected reports matching some keywords and a date interval:
    my @cves = $nvd->search(
        keyword_search      => 'perl cpan',
        last_mod_start_date => '2023-01-01T00:00:00',
        last_mod_end_date   => '2023-04-01T00:00:00',
        no_rejected         => 1,
    );

    foreach my $report (@cves) {
        say "$report->{id} (published in $report->{id}{published})";
        say "$report->{descriptions}[0]{value}";
    }

DESCRIPTION

This modules provides a Perl interface to NIST's National Vulnerability Database (NVD) , allowing developers to search and retrieve CVE (Common Vulnerabilities and Exposures) information.

METHODS

new( %params )

    my $nvd = Net::NVD->new;
    my $nvd = Net::NVD->new(
      api_key => 'your secret key',
      format  => 'complete',
    );

Instantiates a new object. If you want a better rate limit, you should request an API key for your organization. But you should probably only do it if you actually hit the limit, as their API is quite generous.

You may also specify the format of the output. Available are:

  • cve (default) - returns only the actual CVE portion.

  • complete - returns the entire data structure from NVD.

get( $cve_id )

    my $cve_data = $nvd->get( 'CVE-2003-0521' );

Retrieves data for a given CVE. It is a shortcut to:

    my $cve_data = (Net::NVD->new->search(cve_id => 'CVE-2003-0521'))[0]{cve};

search( %params )

    my @cves = $nvd->search(
      keyword_search      => 'Microsoft Outlook',
      keyword_exact_match => true,
    );

Queries NVD's API with the following parameters:

  • cpe_name - a given CPE v2.3 name.

  • cve_id - a specific CVE id.

  • cvssv2_metrics - a full or partial CVSSv2 vector string.

  • cvssV2Severity - LOW, MEDIUM or HIGH.

  • cvssv3_metrics - a full or partial CVSSv3 vector string.

  • cvssv3_severity - LOW, MEDIUM, HIGH or CRITICAL.

  • cwe_id - a CWE (Common Weakness Enumeration) id.

  • has_cert_alerts - set to true to return only CVE's containing a Technical Alert from US-CERT.

  • has_cert_notes - set to true to return only CVE's containing a Vulnerability Note from CERT/CC.

  • has_kev - set to true to return only CVE's that appear in CISA's Known Exploited Vulnerabilities (KEV) Catalog.

  • has_oval - set to true to return only CVE's that contain information from MITRE's Open Vulnerability and Assessment Language (OVAL) before this transitioned to the Center for Internet Security (CIS).

  • is_vulnerable - set to true to return only CVE's associated with a specific CPE, where the CPE is also considered vulnerable (if you use this parameter, you must also set cpe_name).

  • keyword_search - return CVE's with ANY of the given words found in the current description. To search for an exact phrase, set keyword_exact_match to true.

  • keyword_exact_match - set to true to make keyword_search look for an exact phrase match.

  • last_mod_start_date / last_mod_end_date - CVE's that were last modified during the specified period (iso8061 format). Must be used together.

  • no_rejected - set to true to return only CVE records with the REJECT or Rejected status.

  • pub_start_date / pub_end_date - CVE's that were added to NVD (i.e. published) during the specified period (iso8061 format). Must be used together.

  • results_per_page - maximum number of CVE records to return. Defaults to the maximum of 2_000 (and NIST recommends you keep it like so).

  • start_index - the index of the first CVE to be returned in the response data (zero based).

  • source_identifier - CVE records with the given source identifier appearing as a data source in the CVE record.

  • virtual_match_string - a broader CPE filter than cpe_name. May be augmented by the parameters below.

  • version_end - augments virtual_match_string filtering CPE's in specific version ranges.

  • version_end_type - 'including' or 'excluding', specifying the type for version_end.

  • version_start - augments virtual_match_string filtering CPE's in the specific version ranges.

  • version_start_type - 'including' or 'excluding', specifying the type for version_start.

Please refer to NIST NVD API Specification for more information on the search parameters above.

Return Values

A typical CVE portion on this API looks like this:

    {
      configurations => [{
          nodes => [{
            cpeMatch => [{
              criteria => '(some CPE value)',
              matchCriteriaId => '(some id)',
              vulnerable => true,
            }],
            negate   => false,
            operator => 'OR',
          }],
      }],
      descriptions => [
        {
          lang  => 'en',
          value => 'the CVE description, in english',
        },
        {
          lang  => 'es',
          value => 'la descripción del CVE, en español',
        },
      ],
      id => 'CVE-YYYY-NNNNN',  # the current CVE id
      lastModified => 'YYYY-MM-DDThh:mm:ss',
      metricts => {
        cvssMetricV2  => [{ ... }],
        cvssMetricV30 => [{ ... }],
        cvssMetricV31 => [{ ... }],
      },
      published => 'YYYY-MM-DDThh:mm:ss',
      references => [
        {
          source => 'source handle',
          tags => [ 'tag1', 'tag2', ... ],
          url => 'where to find the reference',
        },
        { ...}
      ],
      sourceIdentifier => 'source handle',
      vulnStatus => 'Analyzed',
      weaknesses => [{
        description => [{ lang => 'en', value => 'CWD-NNNN' }],
        source      => 'source handle',
        type        => 'Primary',
      }],
    }

Expect a single one of these when you call get(), and an array of these when you call search(). If you have set the format to 'complete', the return value will instead be:

    {
      format => 'NVD_CVE',
      resultsPerPage => 10,  # some integer
      startIndex     => 0,   # some integer
      timestamp      => 'YYYY-MM-DDThh:mm:ss', # when the request was processed
      totalResults   => 4,   # some integer
      version        => 2.0, # API version
      vulnerabilities => [
        { cve => $cve_hashref },
        { cve => $cve_hashref },
        ...
      ],
    }

Of course, when your result only have one CVE (e.g. you called get()), the 'complete' format will still include this header, but you can expect only one element in $ret->vulnerabilities->[0].

NOTE: NVD mentions there could be up to four different JSON formats. Please check here to get extra information on possible return values. If in doubt, request in 'complete' format and dump the output using a tool like Data::Printer (DDP).

    my $result = Net::NVD->new( format => 'complete' )->get('CVE-2003-0521');
    use DDP; p $result;

SEE ALSO

Net::OSV

Net::CVE

CPAN::Audit

LICENSE AND COPYRIGHT

Copyright 2023- Breno G. de Oliveira <garu at cpan.org>. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

This product uses data from the NVD API but is not endorsed or certified by the NVD.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 249:

Non-ASCII character seen before =encoding in 'descripción'. Assuming UTF-8