diff --git a/security/vuxml/Makefile b/security/vuxml/Makefile
--- a/security/vuxml/Makefile
+++ b/security/vuxml/Makefile
@@ -102,10 +102,6 @@
@${ECHO_CMD} 'Also, tags are usually wrong in ranges. Use where adequate.'
@${ECHO_CMD}
@${SH} ${FILESDIR}/newentry.sh "${VUXML_CURRENT_FILE}" "CVE_ID=${CVE_ID}" "SA_ID=${SA_ID}"
- @${ECHO_CMD}
- @${ECHO_CMD} 'Be sure to get versioning right for PORTEPOCH and remember possible linux-* ports!'
- @${ECHO_CMD} 'Also, tags are usually wrong in ranges. Use where adequate.'
- @${ECHO_CMD}
.if defined(VID) && !empty(VID)
html: work/${VID}.html
diff --git a/security/vuxml/files/euvd_provider.sh b/security/vuxml/files/euvd_provider.sh
new file mode 100644
--- /dev/null
+++ b/security/vuxml/files/euvd_provider.sh
@@ -0,0 +1,69 @@
+# Provider for the European Union Vulnerability Database
+# https://euvd.enisa.europa.eu/
+
+tmp_euvd=""
+
+init_euvd() {
+ tmp_euvd=$(mktemp "${TMPDIR:-/tmp}"/euvd_json_data.XXXXXXXXXX) || exit 1
+ fetch -q -o "${tmp_euvd}" "https://euvdservices.enisa.europa.eu/api/enisaid?id=${CVE_ID}" || exit 1
+}
+
+cleanup_euvd() {
+ rm -f "${tmp_euvd}" 2>/dev/null
+}
+
+get_cvename_from_euvd() {
+ # EUVD response includes "aliases" (CVE ID if available)
+ jq -r '.aliases // .id' "${tmp_euvd}"
+}
+
+get_cveurl_from_euvd() {
+ echo "https://euvd.enisa.europa.eu/ui/vuln/${CVE_ID}"
+}
+
+get_details_from_euvd() {
+ jq -r '.description // empty | @html' "${tmp_euvd}" | fmt -p -s | sed '1!s/^/\t/'
+}
+
+get_discovery_date_from_euvd() {
+ raw=$(jq -r '.datePublished // empty' "${tmp_euvd}")
+ if [ -n "$raw" ]; then
+ trimmed=$(echo "$raw" | cut -d, -f1-2)
+ if date -d "$trimmed" "+%Y-%m-%d" >/dev/null 2>&1; then
+ date -d "$trimmed" "+%Y-%m-%d"
+ else
+ date -j -f "%b %d, %Y" "$trimmed" "+%Y-%m-%d"
+ fi
+ fi
+}
+
+get_entry_date_from_euvd() {
+ echo "${entry_date}"
+}
+
+
+get_product_name_from_euvd() {
+ jq -r ' .enisaIdProduct[]?.product?.name ' "${tmp_euvd}"
+}
+
+get_product_range_from_euvd() {
+ jq -r '.enisaIdProduct[]? | "\(.product_version? | gsub("<";"<") | gsub(">";">") | gsub("&";"&"))"' "${tmp_euvd}"
+}
+
+get_package_name_from_euvd() {
+ jq -r '.enisaIdProduct[0]?.product?.name // empty' "${tmp_euvd}"
+}
+
+get_references_from_euvd() {
+ jq -r '.references // empty | @html' "${tmp_euvd}" | tr " " "\n"
+}
+
+get_source_from_euvd() {
+ jq -r '.assigner // empty | @html' "${tmp_euvd}"
+}
+
+get_topic_from_euvd() {
+ # Use first sentence of description
+ jq -r '.description // empty' "${tmp_euvd}" | cut -f1 -d.
+}
+
diff --git a/security/vuxml/files/mitre_provider.sh b/security/vuxml/files/mitre_provider.sh
new file mode 100644
--- /dev/null
+++ b/security/vuxml/files/mitre_provider.sh
@@ -0,0 +1,61 @@
+# Provider for MITRE
+# https://www.mitre.org/
+
+tmp_mitre=""
+
+init_mitre()
+{
+ tmp_mitre=$(mktemp "${TMPDIR:-/tmp}"/mitre.XXXXXXXXXX) || exit 1
+ fetch -q -o "${tmp_mitre}" https://cveawg.mitre.org/api/cve/"${CVE_ID}"
+}
+
+cleanup_mitre()
+{
+ rm "${tmp_mitre}" 2>/dev/null
+}
+
+get_cvename_from_mitre()
+{
+ cvename="${CVE_ID}"
+ echo "${cvename}"
+}
+
+get_cveurl_from_mitre() {
+ echo https://cveawg.mitre.org/api/cve/"${CVE_ID}"
+}
+
+get_details_from_mitre() {
+ jq -r '.containers?.cna?.descriptions[0]?.value' "${tmp_mitre}" | fmt -p -s
+}
+
+get_discovery_date_from_mitre() {
+ jq -r '.cveMetadata?.datePublished?' "${tmp_mitre}" | cut -f1 -dT
+}
+
+get_entry_date_from_mitre() {
+ echo "${entry_date}"
+}
+
+get_product_name_from_mitre() {
+ jq -r '.containers?.cna?.affected[]?.product' "${tmp_mitre}"
+}
+
+get_product_range_from_mitre() {
+ jq -r '.containers?.cna?.affected[]??.versions[0]?.lessThan' "${tmp_mitre}"
+}
+
+get_package_name_from_mitre() {
+ jq -r '.containers?.cna?.affected[0]?.product' "${tmp_mitre}"
+}
+
+get_references_from_mitre() {
+ jq -r '.containers?.cna?.references[0]?.url' "${tmp_mitre}" | fmt -p -s
+}
+
+get_source_from_mitre() {
+ jq -r '.containers?.cna?.references[0]?.url' "${tmp_mitre}"
+}
+
+get_topic_from_mitre() {
+ jq -r ".containers?.cna?.problemTypes[0]?.descriptions[0]?.description" "${tmp_mitre}"
+}
diff --git a/security/vuxml/files/newentry.sh b/security/vuxml/files/newentry.sh
--- a/security/vuxml/files/newentry.sh
+++ b/security/vuxml/files/newentry.sh
@@ -15,6 +15,9 @@
show_usage
fi
+# -----------------
+# Process arguments
+# -----------------
shift
while [ $# -gt 0 ]; do
case "$1" in
@@ -34,27 +37,45 @@
esac
done
-tmp="`mktemp ${TMPDIR:-/tmp}/vuxml.XXXXXXXXXX`" || exit 1
+tmp=$(mktemp "${TMPDIR:-/tmp}"/vuxml.XXXXXXXXXX) || exit 1
tmp_fbsd_sa=""
-tmp_mitre=""
-tmp_nvd=""
+# -------------------------------------
+# Define how to clean up temporal files
+# -------------------------------------
+#
doclean="yes"
cleanup() {
if [ "${doclean}" = "yes" ]; then
- rm -f "${tmp}" "${tmp_fbsd_sa}" "${tmp_mitre}" "${tmp_nvd}" > /dev/null
+ rm -f "${tmp}" "${tmp_fbsd_sa}" > /dev/null
fi
+
+ # Call cleaners for providers
+ for provider in ${providers}; do
+ cleanup_"${provider}"
+ cleanup_"${provider}"
+ done
}
-trap cleanup EXIT 1 2 13 15
+trap cleanup EXIT HUP INT PIPE TERM
-vid="`uuidgen | tr '[:upper:]' '[:lower:]'`"
+# -----------------------------
+# Variables with default values
+# -----------------------------
+vid="$(uuidgen | tr '[:upper:]' '[:lower:]')"
[ -z "$vid" ] && exit 1
+
+discovery_date=""
cvename="INSERT CVE RECORD IF AVAILABLE"
cveurl="INSERT BLOCKQUOTE URL HERE"
details="."
-discovery="`date -u '+%Y-%m'`-FIXME" || exit 1
-entry="`date -u '+%Y-%m-%d'`" || exit 1
+discovery_date="$(date -u '+%Y-%m')-FIXME" || exit 1
+entry_date="$(date -u '+%Y-%m-%d')" || exit 1
package_name=""
+product_name=""
+product_range=""
+package_list="
+
+"
references="INSERT URL HERE"
topic=""
source="SO-AND-SO"
@@ -67,38 +88,65 @@
${source} reports:
@@ -106,14 +154,17 @@
${details}