It is rather tedious making the list of vulnerable tags and branches
for the security notice reports. This script takes the changeset of
the commit that first introduced the flaw and then outputs an XML
snippet listing every tag and branch which contains that vulnerable
changeset. This can be copied straight into the security notice,
meaning we just have to then fill out details of which changeset
and tag fixed the flaw.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
scripts/report-vulnerable-tags.pl | 108 ++++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)
create mode 100644 scripts/report-vulnerable-tags.pl
diff --git a/scripts/report-vulnerable-tags.pl b/scripts/report-vulnerable-tags.pl
new file mode 100644
index 0000000..0b6ea6f
--- /dev/null
+++ b/scripts/report-vulnerable-tags.pl
@@ -0,0 +1,108 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Sort::Versions;
+
+if (int(@ARGV) != 1) {
+ die "syntax: $0 CHANGESET\n";
+}
+
+my $changeset = shift @ARGV;
+
+sub get_tags {
+ my @args = @_;
+
+ my @tags;
+ open GIT, "-|", "git", "tag", @args or
+ die "cannot query 'git tags @args': $!\n";
+
+ while (<GIT>) {
+ chomp;
+
+ # Drop anything except vN.N.N style tags
+ # where 'N' is only digits.
+ if (/^v(\d+)(\.\d+)+$/) {
+ push @tags, $_;
+ }
+ }
+
+ close GIT;
+
+ return @tags;
+}
+
+sub get_branch {
+ my $tag = shift;
+
+ my @branches;
+ open GIT, "-|", "git", "branch", "--all",
"--contains", $tag or
+ die "cannot query 'git branch --all --contains $tag': $!\n";
+
+ while (<GIT>) {
+ chomp;
+
+ if (m,^\s*remotes/origin/(v.*-maint)$,) {
+ push @branches, $1;
+ }
+ }
+
+ close GIT;
+
+ return @branches;
+}
+
+my @branches;
+my %tags;
+my %branches;
+
+$branches{"master"} = [];
+# Most tags live on master so lets get them first
+for my $tag (get_tags("--contains", $changeset, "--merged",
"master")) {
+ push @{$branches{"master"}}, $tag;
+ $tags{$tag} = 1;
+}
+push @branches, "master";
+
+# Now we need slower work to find branches for
+# few remaining tags
+for my $tag (get_tags("--contains", $changeset)) {
+
+ next if exists $tags{$tag};
+
+ my @tagbranches = get_branch($tag);
+ if (int(@tagbranches) == 0) {
+ if ($tag eq "v2.1.0") {
+ @tagbranches = ("master")
+ } else {
+ print "Tag $tag doesn't appear in any branch\n";
+ next;
+ }
+ }
+
+ if (int(@tagbranches) > 1) {
+ print "Tag $tag appears in multiple branches\n";
+ }
+
+ unless (exists($branches{$tagbranches[0]})) {
+ $branches{$tagbranches[0]} = [];
+ push @branches, $tagbranches[0];
+ }
+ push @{$branches{$tagbranches[0]}}, $tag;
+}
+
+
+foreach my $branch (sort versioncmp @branches) {
+ print " <branch>\n";
+ print " <name>$branch</name>\n";
+ foreach my $tag (sort versioncmp @{$branches{$branch}}) {
+ print " <tag
state=\"vulnerable\">$tag</tag>\n";
+ }
+ print " <change
state=\"vulnerable\">$changeset</change>\n";
+
+ if ($branch eq "master") {
+ print " <change state=\"fixed\"></change>\n";
+ }
+ print " </branch>\n";
+}
--
2.14.3