aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Fandrich <danf@mageia.org>2024-03-08 18:33:47 -0800
committerDan Fandrich <danf@mageia.org>2024-03-08 23:55:05 -0800
commitde98902a85982351c7539672391de014252edde5 (patch)
treee6659a58712ffb9c7f99410d3f282ad23ff8dbbf
parent3b4f039b1fc76a1f7cd87b55f74d76da1e9e8e09 (diff)
downloadmgaadvisories-de98902a85982351c7539672391de014252edde5.tar
mgaadvisories-de98902a85982351c7539672391de014252edde5.tar.gz
mgaadvisories-de98902a85982351c7539672391de014252edde5.tar.bz2
mgaadvisories-de98902a85982351c7539672391de014252edde5.tar.xz
mgaadvisories-de98902a85982351c7539672391de014252edde5.zip
Add 'showjson' command to output an advisory in OSV JSON
Open Source Vulnerability format is a standard for publishing vulnerabilities in Open Source projects and is defined at https://ossf.github.io/osv-schema/
-rw-r--r--NEWS1
-rw-r--r--lib/MGA/Advisories.pm23
-rwxr-xr-xmgaadv17
-rw-r--r--tmpl/advisory.json94
4 files changed, 135 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 61c5377..8a16eb6 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Version X
- template: change default CVE year to 2024
- use https: links where possible
+- add 'showjson' command to output an advisory in OSV JSON format
Version 0.27
diff --git a/lib/MGA/Advisories.pm b/lib/MGA/Advisories.pm
index cbabd68..c8514fa 100644
--- a/lib/MGA/Advisories.pm
+++ b/lib/MGA/Advisories.pm
@@ -821,4 +821,27 @@ sub showadv {
print $advtxt;
}
+sub showadvjson {
+ my ($advdb, $adv) = @_;
+ if (!$advdb->{advisories}{$adv}) {
+ print STDERR "Cannot find advisory $adv\n";
+ return undef;
+ }
+ my $template = Template->new(
+ ENCODING => 'utf8',
+ INCLUDE_PATH => $config->{tmpl_dir},
+ EVAL_PERL => 1,
+ );
+ my $vars = {
+ config => $config,
+ advisory => $adv,
+ advdb => $advdb,
+ basename => \%basename,
+ tools => \%tools,
+ };
+ my $advtxt;
+ process_template($template, 'advisory', $vars, \$advtxt, 'json');
+ print $advtxt;
+}
+
1;
diff --git a/mgaadv b/mgaadv
index ca519b0..78b1cf3 100755
--- a/mgaadv
+++ b/mgaadv
@@ -111,6 +111,15 @@ $0 show [ID]
Show an advisory.
END
},
+ showjson => {
+ run => \&showadvjson,
+ descr => 'Show an advisory in JSON format',
+ usage => <<END,
+$0 showjson [ID]
+
+Show an advisory in JSON format.
+END
+ },
update => {
run => \&updateadv,
descr => 'Update the advisories database',
@@ -219,6 +228,14 @@ sub showadv {
MGA::Advisories::showadv(\%advdb, $adv);
}
+sub showadvjson {
+ usageexit('usage', $_[0]) unless @_ == 2;
+ my $adv = $_[1];
+ my %advdb;
+ $advdb{advisories} = MGA::Advisories::get_advisories();
+ MGA::Advisories::showadvjson(\%advdb, $adv);
+}
+
sub updateadv {
usageexit('usage', $_[0]) unless @_ == 1;
MGA::Advisories::download_advisories;
diff --git a/tmpl/advisory.json b/tmpl/advisory.json
new file mode 100644
index 0000000..475012f
--- /dev/null
+++ b/tmpl/advisory.json
@@ -0,0 +1,94 @@
+[% USE date -%]
+[% PERL -%]
+use JSON;
+[% END -%]
+[% MACRO jsonvar(var) PERL -%]
+# JSON-encode the given variable, including quotes
+print JSON::encode_json($stash->get($stash->get('var')));
+[% END %]
+[%- SET adv = advdb.advisories.$advisory -%]
+{
+ "schema_version": "1.6.2",
+ "id": [% jsonvar('advisory') %],
+ "published": "[% date.format(adv.status.published, format => '%Y-%m-%dT%H:%M:%SZ', gmt => 1) %]",
+ "summary": [% jsonvar('adv.subject') %],
+ "details": [% jsonvar('adv.description') %],
+[% IF adv.CVE && adv.CVE.list.size != 0 -%]
+ "related": [
+[% FOREACH cve IN adv.CVE -%]
+ [% jsonvar('cve') -%]
+[% "," IF ! loop.last %]
+[% END -%]
+ ],
+[% END -%]
+ "references": [
+ {
+ "type": "ADVISORY",
+ "url": "[% config.site_url %]/[% basename.ID(advisory) %].html"
+ }
+[%- "," IF adv.references && adv.references.list.size != 0 %]
+[% FOREACH ref IN adv.references -%]
+ {
+ "type": "REPORT",
+ "url": [% jsonvar('ref') %]
+ }
+[%- "," IF ! loop.last %]
+[% END -%]
+ ],
+ "affected": [
+[% USE srciter = iterator(adv.src.keys) -%]
+[% FOREACH rel IN srciter -%]
+[% USE mediaiter = iterator(adv.src.$rel.keys) -%]
+[% FOREACH media IN mediaiter -%]
+[% FOREACH srpm IN adv.src.$rel.$media -%]
+ {
+ "package": {
+ "ecosystem": "Mageia:[% rel %]",
+[% USE pkg = String(srpm) -%]
+[% FOREACH part IN pkg.split('-[\w\.+~^]+-[\w\.]+\.mga\d+') -%]
+[% SET pkgname = part -%]
+[% LAST -%]
+[% END -%]
+ "name": [% jsonvar('pkgname') %],
+[% CALL pkg.shift(pkgname) -%]
+[% CALL pkg.shift('-') -%]
+[% SET pkgver = pkg.text -%]
+[% USE purl = String('pkg:rpm/mageia/') -%]
+[% CALL purl.push(pkgname) -%]
+[% CALL purl.push('?distro=mageia-') -%]
+[% CALL purl.push(rel) -%]
+[% SET purltext = purl.text -%]
+ "purl": [% jsonvar('purltext') %]
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": [% jsonvar('pkgver') %]
+ }
+ ]
+ }
+ ],
+ "ecosystem_specific": {
+ "section": [% jsonvar('media') %]
+ }
+ }
+[%- "," IF ! loop.last || ! mediaiter.last || ! srciter.last %]
+[% END %]
+[%- END -%]
+[%- END -%]
+ ],
+ "credits": [
+ {
+ "name": "Mageia",
+ "type": "COORDINATOR",
+ "contact": [
+ "https://wiki.mageia.org/en/Packages_Security_Team"
+ ]
+ }
+ ]
+}