diff mbox series

[web,2/4] Introduce content and tools for managing security notices

Message ID 20181018145203.11336-3-berrange@redhat.com (mailing list archive)
State New, archived
Headers show
Series Add web section reporting information about CVEs in QEMU | expand

Commit Message

Daniel P. Berrangé Oct. 18, 2018, 2:52 p.m. UTC
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 _config.yml                                  |   4 +
 _includes/nav.html                           |   3 +-
 _layouts/secnotice.html                      |  22 ++
 assets/css/style.css                         |  47 +++
 secnotice/Makefile                           |  40 +++
 secnotice/README-template.md                 |  78 +++++
 secnotice/README.md                          |  20 ++
 secnotice/_scripts/index-html.xsl            |  72 +++++
 secnotice/_scripts/index-xml                 |  28 ++
 secnotice/_scripts/notice-html.xsl           | 286 +++++++++++++++++++
 secnotice/_scripts/notice-txt.xsl            | 277 ++++++++++++++++++
 secnotice/_scripts/report-vulnerable-tags.pl | 135 +++++++++
 secnotice/template.xml                       |  50 ++++
 13 files changed, 1061 insertions(+), 1 deletion(-)
 create mode 100644 _layouts/secnotice.html
 create mode 100644 secnotice/Makefile
 create mode 100644 secnotice/README-template.md
 create mode 100644 secnotice/README.md
 create mode 100644 secnotice/_scripts/index-html.xsl
 create mode 100755 secnotice/_scripts/index-xml
 create mode 100644 secnotice/_scripts/notice-html.xsl
 create mode 100644 secnotice/_scripts/notice-txt.xsl
 create mode 100644 secnotice/_scripts/report-vulnerable-tags.pl
 create mode 100644 secnotice/template.xml
diff mbox series

Patch

diff --git a/_config.yml b/_config.yml
index 0a0201c..6fddace 100644
--- a/_config.yml
+++ b/_config.yml
@@ -37,3 +37,7 @@  gems:
 exclude:
   - Gemfile
   - Gemfile.lock
+  - Makefile
+  - secalert/README.md
+  - secalert/README-template.md
+  - secalert/template.xml
diff --git a/_includes/nav.html b/_includes/nav.html
index 241d83e..350de6d 100644
--- a/_includes/nav.html
+++ b/_includes/nav.html
@@ -6,7 +6,8 @@ 
 			</li><li {% if current[1] == 'download' %}class='current'{% endif %}><a href="/download">Download</a>
 			</li><li {% if current[1] == 'contribute' %}class='current'{% endif %}><a href="/contribute">Contribute</a>
 			</li><li {% if current[1] == 'documentation' %}class='current'{% endif %}><a href="/documentation">Documentation</a>
-			</li><li {% if current[1] == 'blog' %}class='current'{% endif %}><a href="/blog">Blog</a></li>
+			</li><li {% if current[1] == 'blog' %}class='current'{% endif %}><a href="/blog">Blog</a>
+			</li><li {% if current[1] == 'secnotice' %}class='current'{% endif %}><a href="/secnotice">Security Notices</a></li>
 		</ul>
 	</nav>
 
diff --git a/_layouts/secnotice.html b/_layouts/secnotice.html
new file mode 100644
index 0000000..b30c036
--- /dev/null
+++ b/_layouts/secnotice.html
@@ -0,0 +1,22 @@ 
+<!DOCTYPE HTML>
+<!--
+Linear by TEMPLATED
+templated.co @templatedco
+Released for free under the Creative Commons Attribution 3.0 license (templated.co/license)
+-->
+<html>
+<head>
+	<title>{{ page.title }} - {{ site.title }}</title>
+	{% include assets.html %}
+</head>
+<body class="secnotice">
+
+	{% include nav.html %}
+
+	{{ content }}
+
+	{% include footer.html %}
+	{% include copyright.html %}
+
+</body>
+</html>
diff --git a/assets/css/style.css b/assets/css/style.css
index b828887..dccffb0 100644
--- a/assets/css/style.css
+++ b/assets/css/style.css
@@ -590,3 +590,50 @@ 
 	{
 		margin-top: 1.5em;
 	}
+
+/*********************************************************************************/
+/* Security notices                                                              */
+/*********************************************************************************/
+
+	body.secnotice #main
+	{
+		width: 50%;
+	}
+
+	body.secnotice #sidebar
+	{
+		margin-top: 10em;
+		width: 30%;
+	}
+
+	body.secnotice p.altformat
+	{
+		font-size: smaller;
+		color: inherit;
+		text-align: right;
+	}
+
+	body.secnotice table.repository {
+	    border-spacing: 0px;
+	}
+
+	body.secnotice table.repository tbody th {
+	    text-align: right;
+	}
+
+	body.secnotice table.repository tbody th,
+	body.secnotice table.repository tbody td {
+	    padding: 2px;
+	}	
+
+	body.secnotice table.repository tbody td.fixedtag,
+	body.secnotice table.repository tbody td.mergedcommit {
+	    background: rgb(240,255,240);
+	}
+	body.secnotice table.repository tbody td.fixedcommit {
+	    background: rgb(240,240,255);
+	}
+
+	body.secnotice table.repository thead {
+	    background: rgb(240,240,240);
+	}
diff --git a/secnotice/Makefile b/secnotice/Makefile
new file mode 100644
index 0000000..fef2e8c
--- /dev/null
+++ b/secnotice/Makefile
@@ -0,0 +1,40 @@ 
+
+YEARS = $(wildcard 2???)
+
+INDEX_XML = index.xml $(YEARS:%=%/index.xml)
+INDEX_HTML = $(INDEX_XML:%.xml=%.html)
+
+NOTICE_XML = $(wildcard */???.xml)
+NOTICE_TXT = $(NOTICE_XML:%.xml=%.txt)
+NOTICE_HTML = $(NOTICE_XML:%.xml=%.html)
+
+all: $(INDEX_XML) $(INDEX_HTML) $(NOTICE_TXT) $(NOTICE_HTML)
+
+index.xml: $(NOTICE_XML) _scripts/index-xml Makefile
+	mkdir -p `dirname $@`
+	_scripts/index-xml $(sort $(NOTICE_XML)) > $@
+
+index.html: index.xml _scripts/index-html.xsl Makefile
+	xsltproc _scripts/index-html.xsl $< > $@
+
+%/index.xml: $(NOTICE_XML) _scripts/index-xml Makefile
+	mkdir -p `dirname $@`
+	DIR=`echo $@ | sed -e 's,/index.xml,,'`
+	rm -f $@
+	_scripts/index-xml $(sort $(wildcard $(@:%/index.xml=%/)???.xml)) > $@
+
+%/index.html: %/index.xml _scripts/index-html.xsl Makefile
+	xsltproc --stringparam permalink $(@:%/index.html=/secnotice/%/) _scripts/index-html.xsl $< > $@
+
+%.txt: %.xml _scripts/notice-txt.xsl Makefile
+	mkdir -p `dirname $@`
+	xsltproc _scripts/notice-txt.xsl $< > $@
+
+%.html: %.xml _scripts/notice-html.xsl Makefile
+	mkdir -p `dirname $@`
+	xsltproc _scripts/notice-html.xsl $< > $@
+
+clean:
+	rm -rf index.{xml,html}
+	rm -rf */index.{xml,html}
+	rm -rf */*.{txt,html}
diff --git a/secnotice/README-template.md b/secnotice/README-template.md
new file mode 100644
index 0000000..2b80dca
--- /dev/null
+++ b/secnotice/README-template.md
@@ -0,0 +1,78 @@ 
+QEMU Security Notice Schema
+===========================
+
+The top level element of a QEMU security notice has a name of
+``security-notice`` and is in an XML namespace of
+``http://qemu.org/xmlns/security-notice/1.0``
+
+Basic metadata
+--------------
+
+The ``id`` element content is a pair of 4 digit numbers uniquely identifying
+the security issue. By convention the first 4 digit number is the year in which
+it was reported and the second number is an integer value that is unique within
+the year, monotonically incrementing from 1. eg the 137th issue reported in
+2013 would have an id of ``2013-0137``
+
+The ``summary`` element is a short, single line description of the flaw,
+ideally 80 characters or less to make it suitable for use in email subject
+lines or git commit messages.
+
+The ``credits`` element provides information on persons involved with the flaw.
+It permits the child elements ``reporter`` or ``patcher`` each of which can be
+repeated zero or more times. Both elements contain two further child elements
+``email`` and ``name`` with the former providing the email address and the
+latter providing the full name. At least one of ``email`` and ``name`` must
+be provided.
+
+The ``lifecycle`` element provides date on key milestones in handling of the
+issue. It contains between one and three child elements, ``reported``,
+``published`` and ``fixed``. The ``reported`` element says the date on which
+the QEMU security received notification of the issue. The ``published`` element
+says the date on which the issue was revealed to the public. The ``fixed``
+element says the date on which the issue was patched in the primary code branch
+(typically GIT master).
+
+The ``reference`` element provides details of related resources. It will have
+one or more child elements which can be either ``advisory`` or ``bug``. An
+``advisory`` element includes a ``type`` and ``id`` attribute where ``type`` is
+currently allowed to be ``CVE`` and ``id`` is the identifier of the report. A
+``bug`` element includes ``tracker`` and ``id`` attributes where ``tracker`` is
+allowed to be ``redhat``, ``debian`` or a short name for another vendors' bug
+tracker.
+
+Descriptive data
+----------------
+
+There are three free form text elements providing descriptive data about the
+issue. The data will usually be inside a CDATA block.
+
+The ``description`` element content is an expanded version of the ``summary``
+element content, describing what the flaw is.
+
+The ``impact`` element content describes the implications of the security
+issue. ie what can a malicious user do with the flaw.
+
+The ``workaround`` element content describes any steps that an administrator
+can take to eliminate or at least mitigate the impact of the flaw.
+
+
+Product data
+------------
+
+The ``product`` element provides information about the codebase of the affected
+products. The ``name`` attribute is the name of a QEMU product, typically based
+on the tar.gz archive name with the suffix stripped. This contains a child
+``repository`` element which is a URL to the master GIT repository. There is
+then one or more ``branch`` elements which details the state of affected
+branches.
+
+The first child of the ``branch`` element is a ``name`` giving the branch name,
+eg ``master``, ``v1.0.1-maint``, etc. There are then zero or more ``tag`` or
+``change`` child elements with a ``state`` attribute of ``vulnerable`` or
+``fixed``. The ``tag`` element content details the name of the GIT tag(s) on
+that branch are vulnerable and which tags are fixed. The ``change`` element
+content details the GIT hash of the change(s) which both introduce and fix the
+flaw. The same vulnerable change hash may appear under multiple ``branch``
+elements since branches will share large portions of their history. The fix
+hash will however usually be different.
diff --git a/secnotice/README.md b/secnotice/README.md
new file mode 100644
index 0000000..643076d
--- /dev/null
+++ b/secnotice/README.md
@@ -0,0 +1,20 @@ 
+QEMU Security Notices
+=====================
+
+This directory records all QEMU Security Notices that are issued.
+
+Notices must only added to this directory once any embargo is lifted, since the
+GIT repository is fully public.
+
+Notices are written in XML in a file ``$YEAR/$NUM.xml`` eg ``2014/0001.xml``.
+Assign numbers incrementally as new issues are reported.  More details on the
+XML format can be found in `README-schema.rst``.
+
+When a new notice is published for the first time, send the text rendering of
+the notice to the ``qemu-devel@nongnu.org``
+
+When backporting security fixes to ``stable-X.Y`` branches, update the notice
+with details of the backported changeset hash.
+
+When doing a formal stable release, update the notices included with the release
+tag name.
diff --git a/secnotice/_scripts/index-html.xsl b/secnotice/_scripts/index-html.xsl
new file mode 100644
index 0000000..71ae716
--- /dev/null
+++ b/secnotice/_scripts/index-html.xsl
@@ -0,0 +1,72 @@ 
+<!--
+  - This program is free software; you can redistribute it and/or modify
+  - it under the terms of the GNU General Public License as published by
+  - the Free Software Foundation; either version 2 of the License, or
+  - (at your option) any later version.
+  -
+  - This program is distributed in the hope that it will be useful,
+  - but WITHOUT ANY WARRANTY; without even the implied warranty of
+  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  - GNU General Public License for more details.
+  -
+  - You should have received a copy of the GNU General Public License
+  - along with this program.  If not, see
+  - <http://www.gnu.org/licenses/>.
+  -->
+<xsl:stylesheet
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:qsn="http://qemu.org/xmlns/security-notice/1.0"
+  xmlns:qsnl="http://qemu.org/xmlns/security-notice-list/1.0"
+  exclude-result-prefixes="xsl qsn qsnl"
+  version="1.0">
+
+  <xsl:output omit-xml-declaration="yes" method="xml" indent="yes" />
+
+  <xsl:param name="permalink" select="'/secnotice/'"/>
+
+  <xsl:template match="/qsnl:security-notice-list">---
+title: QEMU Security Notices
+permalink: <xsl:value-of select="$permalink"/>
+---
+
+   <p>
+     If you believe you have identified a new security issue in QEMU, please
+     follow the <a href="https://wiki.qemu.org/SecurityProcess">security process</a>
+     to report it in a non-public way. Do <strong>NOT</strong> use the bug tracker,
+     mailing lists, or IRC to report non-public security issues.
+   </p>
+
+    <ul>
+      <xsl:apply-templates select="qsnl:security-notice">
+	<xsl:sort select="@name" order="descending" />
+      </xsl:apply-templates>
+    </ul>
+
+    <p class="alt">
+      Alternative formats: <a href="index.xml">[xml]</a>
+    </p>
+  </xsl:template>
+
+  <xsl:template name="qsnhref">
+    <xsl:param name="id"/>
+
+    <xsl:variable name="dir" select="substring-before($id, '-')"/>
+    <xsl:variable name="file" select="substring-after($id, '-')"/>
+
+    <xsl:value-of select="concat($dir, '/', $file)"/>
+  </xsl:template>
+
+  <xsl:template match="qsnl:security-notice">
+    <xsl:variable name="notice" select="document(concat('../../', @name))"/>
+    <xsl:variable name="id" select="$notice/qsn:security-notice/qsn:id"/>
+    <xsl:variable name="summary" select="$notice/qsn:security-notice/qsn:summary"/>
+    <xsl:variable name="href">
+      <xsl:call-template name="qsnhref">
+	<xsl:with-param name="id" select="$id"/>
+      </xsl:call-template>
+    </xsl:variable>
+
+    <li><a href="{$href}">QSN-<xsl:value-of select="$id"/>: <xsl:value-of select="$summary"/></a></li>
+  </xsl:template>
+</xsl:stylesheet>
diff --git a/secnotice/_scripts/index-xml b/secnotice/_scripts/index-xml
new file mode 100755
index 0000000..67de29f
--- /dev/null
+++ b/secnotice/_scripts/index-xml
@@ -0,0 +1,28 @@ 
+#!/bin/bash
+#
+# Copyright (C) 2013-2014 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see
+# <http://www.gnu.org/licenses/>.
+
+set -e
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+echo '<security-notice-list xmlns="http://qemu.org/xmlns/security-notice-list/1.0">'
+for n in $@
+do
+  echo "  <security-notice name='/secnotice/$n'/>"
+done
+echo '</security-notice-list>'
diff --git a/secnotice/_scripts/notice-html.xsl b/secnotice/_scripts/notice-html.xsl
new file mode 100644
index 0000000..50ba802
--- /dev/null
+++ b/secnotice/_scripts/notice-html.xsl
@@ -0,0 +1,286 @@ 
+<!--
+  - This program is free software; you can redistribute it and/or modify
+  - it under the terms of the GNU General Public License as published by
+  - the Free Software Foundation; either version 2 of the License, or
+  - (at your option) any later version.
+  -
+  - This program is distributed in the hope that it will be useful,
+  - but WITHOUT ANY WARRANTY; without even the implied warranty of
+  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  - GNU General Public License for more details.
+  -
+  - You should have received a copy of the GNU General Public License
+  - along with this program.  If not, see
+  - <http://www.gnu.org/licenses/>.
+  -->
+<xsl:stylesheet
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:qsn="http://qemu.org/xmlns/security-notice/1.0"
+  exclude-result-prefixes="xsl qsn"
+  version="1.0">
+
+  <xsl:output omit-xml-declaration="yes" method="xml" indent="yes" />
+
+  <xsl:template name="selfhref">
+    <xsl:param name="id"/>
+    <xsl:param name="ext"/>
+
+    <xsl:variable name="dir" select="substring-before($id, '-')"/>
+    <xsl:variable name="file" select="substring-after($id, '-')"/>
+
+    <xsl:value-of select="concat('/secnotice/', $dir, '/', $file, $ext)"/>
+  </xsl:template>
+
+  <xsl:template match="/qsn:security-notice">---
+title: 'QSN-<xsl:value-of select="qsn:id"/>: <xsl:value-of select="qsn:summary"/>'
+layout: secnotice
+permalink: <xsl:call-template name="selfhref">
+  <xsl:with-param name="id" select="qsn:id"/>
+</xsl:call-template>
+---
+
+    <div id="main">
+      <div class="container">
+
+	<h2>
+	  <xsl:value-of select="qsn:summary"/>
+	</h2>
+
+	<xsl:apply-templates select="qsn:lifecycle"/>
+	<xsl:apply-templates select="qsn:credits"/>
+
+	<xsl:apply-templates select="qsn:reference"/>
+	<xsl:apply-templates select="qsn:description"/>
+	<xsl:apply-templates select="qsn:impact"/>
+	<xsl:apply-templates select="qsn:mitigation"/>
+
+	<xsl:call-template name="selflink"/>
+      </div>
+    </div>
+
+    <div id="sidebar">
+      <div class="container">
+	<section>
+	  <header>
+	    <h2>Related commits</h2>
+	  </header>
+	  <xsl:apply-templates select="qsn:repository"/>
+	</section>
+      </div>
+    </div>
+  </xsl:template>
+
+  <xsl:template name="selflink">
+    <p class="altformat">
+      Alternative formats:
+      <a>
+	<xsl:attribute name="href">
+	  <xsl:call-template name="selfhref">
+	    <xsl:with-param name="id" select="qsn:id"/>
+	    <xsl:with-param name="ext" select="'.xml'"/>
+	  </xsl:call-template>
+	</xsl:attribute>
+	<xsl:text>[xml]</xsl:text>
+      </a>
+      <xsl:text> </xsl:text>
+      <a>
+	<xsl:attribute name="href">
+	  <xsl:call-template name="selfhref">
+	    <xsl:with-param name="id" select="qsn:id"/>
+	    <xsl:with-param name="ext" select="'.txt'"/>
+	  </xsl:call-template>
+	</xsl:attribute>
+	<xsl:text>[text]</xsl:text>
+      </a>
+    </p>
+  </xsl:template>
+
+  <xsl:template match="qsn:lifecycle">
+    <h3>Lifecycle</h3>
+    <table>
+      <tr>
+	<th>Reported on:</th>
+	<td><xsl:value-of select="qsn:reported"/></td>
+      </tr>
+      <tr>
+	<th>Published on:</th>
+	<td><xsl:value-of select="qsn:published"/></td>
+      </tr>
+      <tr>
+	<th>Fixed on:</th>
+	<td><xsl:value-of select="qsn:fixed"/></td>
+      </tr>
+    </table>
+  </xsl:template>
+
+  <xsl:template match="qsn:credits">
+    <h3>Credits</h3>
+    <table>
+      <xsl:for-each select="qsn:reporter">
+	<tr>
+	  <xsl:if test="position() = 1">
+	    <th>Reported by:</th>
+	  </xsl:if>
+	  <xsl:if test="position() > 1">
+	    <th></th>
+	  </xsl:if>
+	  <td>
+	    <a href="mailto:{qsn:email}"><xsl:value-of select="qsn:name"/></a>
+	  </td>
+	</tr>
+      </xsl:for-each>
+      <xsl:for-each select="qsn:patcher">
+	<tr>
+	  <xsl:if test="position() = 1">
+	    <th>Patched by:</th>
+	  </xsl:if>
+	  <xsl:if test="position() > 1">
+	    <th></th>
+	  </xsl:if>
+	  <td>
+	    <a href="mailto:{qsn:email}"><xsl:value-of select="qsn:name"/></a>
+	  </td>
+	</tr>
+      </xsl:for-each>
+    </table>
+  </xsl:template>
+
+  <xsl:template match="qsn:advisory">
+    <xsl:choose>
+      <xsl:when test="@type='CVE'">
+	<a href="https://nvd.nist.gov/vuln/detail/CVE-{@id}">
+	  <xsl:text>CVE-</xsl:text>
+	  <xsl:value-of select="@id"/>
+	</a>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:value-of select="@type"/>
+	<xsl:text>-</xsl:text>
+	<xsl:value-of select="@id"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="qsn:bug">
+    <xsl:value-of select="@tracker"/>
+    <xsl:text> bug #</xsl:text>
+    <xsl:value-of select="@id"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:reference">
+    <h3>See also</h3>
+    <ul>
+    <xsl:for-each select="qsn:advisory|qsn:bug">
+      <li><xsl:apply-templates select="."/></li>
+    </xsl:for-each>
+    </ul>
+  </xsl:template>
+
+  <xsl:template match="qsn:description">
+    <h3>Description</h3>
+    <p>
+      <xsl:value-of select="."/>
+    </p>
+  </xsl:template>
+
+  <xsl:template match="qsn:impact">
+    <h3>Impact</h3>
+    <p>
+      <xsl:value-of select="."/>
+    </p>
+  </xsl:template>
+
+  <xsl:template match="qsn:mitigation">
+    <h3>Mitigation</h3>
+    <p>
+      <xsl:value-of select="."/>
+    </p>
+  </xsl:template>
+
+  <xsl:template name="gitbranch">
+    <xsl:param name="branch"/>
+
+    <a href="http://git.qemu.org/?p=qemu.git;a=shortlog;h=refs/heads/{$branch}"><xsl:value-of select="$branch"/></a>
+  </xsl:template>
+
+  <xsl:template name="gittag">
+    <xsl:param name="tag"/>
+
+    <a href="http://git.qemu.org/?p=qemu.git;a=tag;h={$tag}"><xsl:value-of select="$tag"/></a>
+  </xsl:template>
+
+  <xsl:template name="gitchange">
+    <xsl:param name="change"/>
+
+    <a href="http://git.qemu.org/?p=qemu.git;a=commit;h={$change}"><xsl:value-of select="$change"/></a>
+  </xsl:template>
+
+  <xsl:template match="qsn:repository">
+    <xsl:for-each select="qsn:branch">
+      <table class="repository">
+	<thead>
+	  <tr>
+	    <th colspan="2">Branch:
+	      <xsl:call-template name="gitbranch">
+		<xsl:with-param name="branch" select="qsn:name"/>
+	      </xsl:call-template>
+	    </th>
+	  </tr>
+	</thead>
+	<tbody>
+	  <xsl:for-each select="qsn:tag[@state='fixed']">
+	    <tr>
+	      <th>Fixed in:</th>
+	      <td class="fixedtag">
+		<xsl:call-template name="gittag">
+		  <xsl:with-param name="tag" select="."/>
+		</xsl:call-template>
+	      </td>
+	    </tr>
+	  </xsl:for-each>
+	  <xsl:for-each select="qsn:change[@state='fixed']">
+	    <tr>
+	      <th>Fixed by:</th>
+	      <td class="fixedcommit">
+		<xsl:call-template name="gitchange">
+		  <xsl:with-param name="change" select="."/>
+		</xsl:call-template>
+	      </td>
+	    </tr>
+	  </xsl:for-each>
+	  <xsl:for-each select="qsn:change[@state='merged']">
+	    <tr>
+	      <th>Merged by:</th>
+	      <td class="mergedcommit">
+		<xsl:call-template name="gitchange">
+		  <xsl:with-param name="change" select="."/>
+		</xsl:call-template>
+	      </td>
+	    </tr>
+	  </xsl:for-each>
+	  <xsl:for-each select="qsn:tag[@state='vulnerable']">
+	    <tr>
+	      <th>Broken in:</th>
+	      <td class="brokentag">
+		<xsl:call-template name="gittag">
+		  <xsl:with-param name="tag" select="."/>
+		</xsl:call-template>
+	      </td>
+	  </tr>
+	  </xsl:for-each>
+	  <xsl:for-each select="qsn:change[@state='vulnerable']">
+	    <tr>
+	      <th>Broken by:</th>
+	      <td class="brokencommit">
+		<xsl:call-template name="gitchange">
+		  <xsl:with-param name="change" select="."/>
+		</xsl:call-template>
+	      </td>
+	    </tr>
+	  </xsl:for-each>
+	</tbody>
+      </table>
+    </xsl:for-each>
+  </xsl:template>
+</xsl:stylesheet>
diff --git a/secnotice/_scripts/notice-txt.xsl b/secnotice/_scripts/notice-txt.xsl
new file mode 100644
index 0000000..dc4c125
--- /dev/null
+++ b/secnotice/_scripts/notice-txt.xsl
@@ -0,0 +1,277 @@ 
+<!--
+  - This program is free software; you can redistribute it and/or modify
+  - it under the terms of the GNU General Public License as published by
+  - the Free Software Foundation; either version 2 of the License, or
+  - (at your option) any later version.
+  -
+  - This program is distributed in the hope that it will be useful,
+  - but WITHOUT ANY WARRANTY; without even the implied warranty of
+  - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  - GNU General Public License for more details.
+  -
+  - You should have received a copy of the GNU General Public License
+  - along with this program.  If not, see
+  - <http://www.gnu.org/licenses/>.
+  -->
+<xsl:stylesheet
+  xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:qsn="http://qemu.org/xmlns/security-notice/1.0"
+  exclude-result-prefixes="xsl qsn"
+  version="1.0">
+
+  <xsl:output method="text"/>
+
+  <xsl:variable name="nl">
+    <xsl:text>
+</xsl:text>
+  </xsl:variable>
+
+  <!-- based on http://plasmasturm.org/log/xslwordwrap/ -->
+  <!-- Copyright 2010 Aristotle Pagaltzis; under the MIT licence -->
+  <!-- http://www.opensource.org/licenses/mit-license.php -->
+  <xsl:template name="wrap-string">
+    <xsl:param name="str" />
+    <xsl:param name="wrap-col" />
+    <xsl:param name="break-mark" />
+    <xsl:param name="pos" select="0" />
+    <xsl:choose>
+      <xsl:when test="contains( $str, ' ' )">
+	<xsl:variable name="first-word" select="substring-before( $str, ' ' )" />
+	<xsl:variable name="pos-now" select="$pos + 1 + string-length( $first-word )" />
+	<xsl:choose>
+          <xsl:when test="$pos > 0 and $pos-now >= $wrap-col">
+            <xsl:copy-of select="$break-mark" />
+            <xsl:call-template name="wrap-string">
+              <xsl:with-param name="str" select="$str" />
+              <xsl:with-param name="wrap-col" select="$wrap-col" />
+              <xsl:with-param name="break-mark" select="$break-mark" />
+              <xsl:with-param name="pos" select="0" />
+            </xsl:call-template>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:if test="$pos > 0">
+              <xsl:text> </xsl:text>
+            </xsl:if>
+            <xsl:value-of select="$first-word" />
+            <xsl:call-template name="wrap-string">
+              <xsl:with-param name="str" select="substring-after( $str, ' ' )" />
+              <xsl:with-param name="wrap-col" select="$wrap-col" />
+              <xsl:with-param name="break-mark" select="$break-mark" />
+              <xsl:with-param name="pos" select="$pos-now" />
+            </xsl:call-template>
+          </xsl:otherwise>
+	</xsl:choose>
+      </xsl:when>
+      <xsl:otherwise>
+	<xsl:choose>
+          <xsl:when test="$pos + string-length( $str ) >= $wrap-col">
+            <xsl:copy-of select="$break-mark" />
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:if test="$pos > 0">
+              <xsl:text> </xsl:text>
+            </xsl:if>
+          </xsl:otherwise>
+	</xsl:choose>
+	<xsl:value-of select="$str" />
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="/qsn:security-notice">
+    <xsl:text>        QEMU Security Notice: QSN-</xsl:text>
+    <xsl:value-of select="qsn:id"/>
+    <xsl:value-of select="$nl"/>
+    <xsl:text>        ==================================</xsl:text>
+    <xsl:value-of select="$nl"/>
+
+    <xsl:value-of select="$nl"/>
+
+
+    <xsl:apply-templates select="qsn:summary"/>
+    <xsl:apply-templates select="qsn:lifecycle"/>
+    <xsl:apply-templates select="qsn:credits"/>
+    <xsl:apply-templates select="qsn:reference"/>
+    <xsl:apply-templates select="qsn:description"/>
+    <xsl:apply-templates select="qsn:impact"/>
+    <xsl:apply-templates select="qsn:mitigation"/>
+    <xsl:apply-templates select="qsn:repository"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:summary">
+    <xsl:text>       Summary: </xsl:text>
+    <xsl:call-template name="wrap-string">
+      <xsl:with-param name="str" select="normalize-space(.)"/>
+      <xsl:with-param name="wrap-col" select="52"/>
+      <xsl:with-param name="break-mark" select="concat($nl, '                ')"/>
+    </xsl:call-template>
+    <xsl:value-of select="$nl"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:lifecycle">
+    <xsl:text>   Reported on: </xsl:text>
+    <xsl:value-of select="qsn:reported"/>
+    <xsl:value-of select="$nl"/>
+
+    <xsl:text>  Published on: </xsl:text>
+    <xsl:value-of select="qsn:published"/>
+    <xsl:value-of select="$nl"/>
+
+    <xsl:text>      Fixed on: </xsl:text>
+    <xsl:value-of select="qsn:fixed"/>
+    <xsl:value-of select="$nl"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:credits">
+    <xsl:text>   Reported by: </xsl:text>
+    <xsl:for-each select="qsn:reporter">
+      <xsl:if test="position() > 1">
+	<xsl:text>                </xsl:text>
+      </xsl:if>
+      <xsl:value-of select="qsn:name"/>
+      <xsl:text> &lt;</xsl:text>
+      <xsl:value-of select="qsn:email"/>
+      <xsl:text>&gt;</xsl:text>
+      <xsl:if test="position() != last()">
+	<xsl:value-of select="$nl"/>
+      </xsl:if>
+    </xsl:for-each>
+    <xsl:value-of select="$nl"/>
+    <xsl:text>    Patched by: </xsl:text>
+    <xsl:for-each select="qsn:patcher">
+      <xsl:if test="position() > 1">
+	<xsl:text>                </xsl:text>
+      </xsl:if>
+      <xsl:value-of select="qsn:name"/>
+      <xsl:text> &lt;</xsl:text>
+      <xsl:value-of select="qsn:email"/>
+      <xsl:text>&gt;</xsl:text>
+      <xsl:if test="position() != last()">
+	<xsl:value-of select="concat(',',$nl)"/>
+      </xsl:if>
+    </xsl:for-each>
+    <xsl:value-of select="$nl"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:advisory">
+    <xsl:value-of select="@type"/>
+    <xsl:text>-</xsl:text>
+    <xsl:value-of select="@id"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:bug">
+    <xsl:value-of select="@tracker"/>
+    <xsl:text> bug #</xsl:text>
+    <xsl:value-of select="@id"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:reference">
+    <xsl:text>      See also: </xsl:text>
+    <xsl:variable name="refs">
+      <xsl:for-each select="qsn:advisory|qsn:bug">
+	<xsl:apply-templates select="."/>
+	<xsl:if test="position() != last()">
+	  <xsl:text>, </xsl:text>
+	</xsl:if>
+      </xsl:for-each>
+    </xsl:variable>
+    <xsl:call-template name="wrap-string">
+      <xsl:with-param name="str" select="$refs"/>
+      <xsl:with-param name="wrap-col" select="52"/>
+      <xsl:with-param name="break-mark" select="concat($nl, '                ')"/>
+    </xsl:call-template>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:description">
+    <xsl:text>Description</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:text>-----------</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+    <xsl:call-template name="wrap-string">
+      <xsl:with-param name="str" select="normalize-space(.)"/>
+      <xsl:with-param name="wrap-col" select="70"/>
+      <xsl:with-param name="break-mark" select="$nl"/>
+    </xsl:call-template>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:impact">
+    <xsl:text>Impact</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:text>------</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+    <xsl:call-template name="wrap-string">
+      <xsl:with-param name="str" select="normalize-space(.)"/>
+      <xsl:with-param name="wrap-col" select="70"/>
+      <xsl:with-param name="break-mark" select="$nl"/>
+    </xsl:call-template>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+  </xsl:template>
+
+  <xsl:template match="qsn:mitigation">
+    <xsl:text>Mitigation</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:text>----------</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+    <xsl:call-template name="wrap-string">
+      <xsl:with-param name="str" select="normalize-space(.)"/>
+      <xsl:with-param name="wrap-col" select="70"/>
+      <xsl:with-param name="break-mark" select="$nl"/>
+    </xsl:call-template>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+  </xsl:template>
+
+
+  <xsl:template match="qsn:repository">
+    <xsl:text>Related commits</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:text>----------------</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+    <xsl:text>  git://git.qemu.org/qemu.git</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:text>  https://git.qemu.org/?p=qemu.git</xsl:text>
+    <xsl:value-of select="$nl"/>
+    <xsl:value-of select="$nl"/>
+
+    <xsl:for-each    select="qsn:branch">
+      <xsl:text>      Branch: </xsl:text>
+      <xsl:value-of select="qsn:name"/>
+      <xsl:value-of select="$nl"/>
+      <xsl:if test="count(qsn:tag)">
+	<xsl:for-each select="qsn:tag[@state='vulnerable']">
+	  <xsl:text>   Broken in: </xsl:text>
+	  <xsl:value-of select="."/>
+	  <xsl:value-of select="$nl"/>
+	</xsl:for-each>
+	<xsl:for-each select="qsn:tag[@state='fixed']">
+	  <xsl:text>    Fixed in: </xsl:text>
+	  <xsl:value-of select="."/>
+	  <xsl:value-of select="$nl"/>
+	</xsl:for-each>
+      </xsl:if>
+      <xsl:if test="count(qsn:change)">
+	<xsl:for-each select="qsn:change[@state='vulnerable']">
+	  <xsl:text>   Broken by: </xsl:text>
+	  <xsl:value-of select="."/>
+	  <xsl:value-of select="$nl"/>
+	</xsl:for-each>
+	<xsl:for-each select="qsn:change[@state='fixed']">
+	  <xsl:text>    Fixed by: </xsl:text>
+	  <xsl:value-of select="."/>
+	  <xsl:value-of select="$nl"/>
+	</xsl:for-each>
+      </xsl:if>
+      <xsl:value-of select="$nl"/>
+    </xsl:for-each>
+  </xsl:template>
+</xsl:stylesheet>
diff --git a/secnotice/_scripts/report-vulnerable-tags.pl b/secnotice/_scripts/report-vulnerable-tags.pl
new file mode 100644
index 0000000..3b89efd
--- /dev/null
+++ b/secnotice/_scripts/report-vulnerable-tags.pl
@@ -0,0 +1,135 @@ 
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Sort::Versions;
+
+if (int(@ARGV) != 1 && int (@ARGV) != 2) {
+    die "syntax: $0 BROKEN-COMMIT [MERGED-COMMIT]\n";
+}
+
+my $broken = shift @ARGV;
+my $merged = 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/(stable-.*)$,) {
+            push @branches, $1;
+        }
+    }
+
+    close GIT;
+
+    return @branches;
+}
+
+my @branches;
+my %tags;
+my %branches;
+
+my %merged;
+my $mergedtag;
+
+if (defined $merged) {
+    for my $tag (get_tags("--contains", $merged)) {
+	$merged{$tag} = 1;
+	$mergedtag = $tag unless defined $mergedtag;
+    }
+}
+
+$branches{"master"} = [];
+# Most tags live on master so lets get them first
+for my $tag (get_tags("--contains", $broken, "--merged", "master")) {
+    next if exists $merged{$tag};
+    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", $broken)) {
+
+    next if exists $tags{$tag};
+    next if exists $merged{$tag};
+    next if $tag =~ /v\d+\.\d+\.9\d/;
+
+    my @tagbranches = get_branch($tag);
+    if (int(@tagbranches) == 0) {
+	if ($tag =~ "^v0.10") {
+	    @tagbranches = ("stable-0.10")
+	} elsif ($tag =~ "^v0") {
+	    @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";
+    if ($branch eq "master") {
+	print "      <change state=\"fixed\"></change>\n";
+	if (defined $merged) {
+	    print "      <change state=\"merged\">$merged</change>\n";
+	} else {
+	    print "      <change state=\"merged\"></change>\n";
+	}
+	if (defined $mergedtag) {
+	    print "      <tag state=\"fixed\">$mergedtag</tag>\n";
+	} else {
+	    print "      <tag state=\"fixed\"></tag>\n";
+	}
+    }
+
+    foreach my $tag (sort versioncmp @{$branches{$branch}}) {
+        print "      <tag state=\"vulnerable\">$tag</tag>\n";
+    }
+    print "      <change state=\"vulnerable\">$broken</change>\n";
+
+    print "    </branch>\n";
+}
diff --git a/secnotice/template.xml b/secnotice/template.xml
new file mode 100644
index 0000000..8f8a0d4
--- /dev/null
+++ b/secnotice/template.xml
@@ -0,0 +1,50 @@ 
+<security-notice xmlns="http://qemu.org/xmlns/security-notice/1.0">
+  <id>XXXX-XXX</id>
+
+  <summary></summary>
+
+  <description>
+<![CDATA[]]>
+  </description>
+
+  <impact>
+<![CDATA[]]>
+  </impact>
+
+  <workaround>
+<![CDATA[]]>
+  </workaround>
+
+  <credits>
+    <reporter>
+      <name></name>
+      <email></email>
+    </reporter>
+    <patcher>
+      <name></name>
+      <email></email>
+    </patcher>
+  </credits>
+
+  <lifecycle>
+    <reported></reported>
+    <published></published>
+    <fixed></fixed>
+  </lifecycle>
+
+  <reference>
+    <advisory type="CVE" id="XXXX-XXXX"/>
+  </reference>
+
+  <repository>
+    <branch>
+      <name>master</name>
+      <tag state="fixed"></tag>
+      <change state="fixed"></change>
+      <change state="merged"></change>
+      <change state="vulnerable"></change>
+      <tag state="vulnerable"></tag>
+    </branch>
+  </repository>
+
+</security-notice>