Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153213715
D52903.id163529.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D52903.id163529.diff
View Options
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, <gt> tags are usually wrong in ranges. Use <ge> 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, <gt> tags are usually wrong in ranges. Use <ge> 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,42 @@
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=""
references="INSERT URL HERE"
topic=""
source="SO-AND-SO"
@@ -67,38 +85,65 @@
</blockquote>
</body>"
-
-# Try to retrieve information if a CVE identifier was provided
-if [ -n "${CVE_ID}" ]; then
+# --------------------------------
+# Check we have everything we need
+# --------------------------------
+check_dependencies()
+{
if ! command -v jq > /dev/null; then
echo textproc/jq is needed for CVE automatic entry fill
exit 1
fi
+}
- # NVD database only accepts uppercase CVE ids, like CVE-2022-39282, NOT
- # cve-2022-39282.
- CVE_ID=$(echo "${CVE_ID}" | tr '[:lower:]' '[:upper:]') || exit 1
-
- # Get information from the NVD database JSON format
- tmp_nvd="`mktemp ${TMPDIR:-/tmp}/nvd_json_data.XXXXXXXXXX`" || exit 1
- fetch -q -o "${tmp_nvd}" https://services.nvd.nist.gov/rest/json/cves/2.0?cveId="${CVE_ID}" || exit 1
- # Get information from MITRE database (they provide a nice "topic")
- tmp_mitre="`mktemp ${TMPDIR:-/tmp}/mitre.XXXXXXXXXX`" || exit 1
- fetch -q -o "${tmp_mitre}" https://cveawg.mitre.org/api/cve/"${CVE_ID}"
-
- # Create variables from input and online sources
- cvename="${CVE_ID}"
- cveurl=https://nvd.nist.gov/vuln/detail/${CVE_ID}
- pref=.vulnerabilities[0].cve
- details=$(jq -r "${pref}.descriptions[0].value|@html" "${tmp_nvd}" | fmt -p -s | sed '1!s/^/\t/') || exit 1
- discovery=$(jq -r "${pref}.published|@html" "${tmp_nvd}" | cut -f1 -dT) || exit 1
- pref=.vulnerabilities[0].cve.configurations[0].nodes[0].cpeMatch[0]
- package_name=$(jq -r "${pref}.criteria|@html" "${tmp_nvd}" | cut -f4 -d:) || exit 1
- upstream_fix=$(jq -r "${pref}.versionEndExcluding|@html" "${tmp_nvd}") || exit 1
- pref=.vulnerabilities[0].cve.references[0]
- references=$(jq -r "${pref}.url|@html" "${tmp_nvd}" | tr " " "\n") || exit 1
- source=$(jq -r "${pref}.source|@html" "${tmp_nvd}" | tr " " "\n") || exit 1
- topic=$(jq -r ".containers.cna.title|@html" "${tmp_mitre}" ) || exit 1
+# ------------------------------------------
+# List of CVE providers sorted by preference
+# ------------------------------------------
+providers="mitre nvd euvd"
+
+# ------------------------------------------
+# List of fields to query for every provider
+# ------------------------------------------
+fields="cvename cveurl details discovery_date entry_date product_name product_range package_name references source topic"
+
+# Some providers only allow for upper case identifiers
+CVE_ID=$(echo "${CVE_ID}" | tr '[:lower:]' '[:upper:]') || exit 1
+
+# -----------------------------------------------------------------------------
+# Generic resolver
+#
+# Gets a variable name and the list of providers and returns the value of the
+# variable. If the first defined provider returns empty or nullm, it tries with
+# the next one until one provider returns a value or we run out of providers
+# -----------------------------------------------------------------------------
+resolve_field() {
+ field="${1}"
+ shift
+ providers="$@"
+
+ for provider in $providers; do
+ func="get_${field}_from_${provider}"
+ if command -v "${func}" >/dev/null 2>&1; then
+ value="$($func)"
+ if [ -n "${value}" ] && [ "${value}" != "null" ] && [ "${value}" != "n/a" ]; then
+ echo "${value}"
+ return 0
+ fi
+ else
+ echo "Warning: function ${func} not implemented"
+ fi
+ done
+ echo "null"
+}
+
+# --------------------------------------------------
+# Fill global variables with data from CVE databases
+# --------------------------------------------------
+get_cve_info() {
+ for field in ${fields}; do
+ value=$(resolve_field "${field}" ${providers})
+ eval "${field}=\$value"
+ done
DESC_BODY="<body xmlns=\"http://www.w3.org/1999/xhtml\">
<p>${source} reports:</p>
@@ -106,14 +151,17 @@
<p>${details}</p>
</blockquote>
</body>"
-fi
+}
-if [ -n "${SA_ID}" ]; then
+# ----------------------------------------------------------------
+# Fill global variables with data from FreeBSD Security Advisories
+# ----------------------------------------------------------------
+get_sa_info() {
SA_URL_BASE=https://www.freebsd.org/security/advisories/
# Get information from the Project's SA site
- tmp_fbsd_sa="$(mktemp ${TMPDIR:-/tmp}/fbsd_sa_data.XXXXXXXXXX)" || exit 1
- fetch -q -o "${tmp_fbsd_sa}" ${SA_URL_BASE}${SA_ID} || exit 1
+ tmp_fbsd_sa=$(mktemp "${TMPDIR:-/tmp}/fbsd_sa_data.XXXXXXXXXX") || exit 1
+ fetch -q -o "${tmp_fbsd_sa}" "${SA_URL_BASE}${SA_ID}" || exit 1
# Create variables from SA note
if grep -q 'CVE Name' "${tmp_fbsd_sa}"; then
@@ -148,6 +196,25 @@
<h1>Impact:</h1>
${impact}
</body>"
+}
+
+init_providers() {
+ for provider in files/*_provider.sh; do
+ provider_name=$(basename "${provider}" | cut -f1 -d_)
+ . "files/${provider_name}_provider.sh"
+ init_"${provider_name}"
+ done
+}
+
+# Try to retrieve information if a CVE identifier was provided
+if [ -n "${CVE_ID}" ]; then
+ check_dependencies
+ init_providers
+ get_cve_info "${CVE_ID}"
+fi
+
+if [ -n "${SA_ID}" ]; then
+ get_sa_info
fi
awk '/^<\?/,/^<vuxml/ { print }' "${vuxml_file}" >> "${tmp}" || exit 1
@@ -156,20 +223,20 @@
<topic>${package_name} -- ${topic}</topic>
<affects>
<package>
- <name>${package_name}</name>
- <range><lt>${upstream_fix}</lt></range>
+ <name>${product_name}</name>
+ <range><lt>${product_range}</lt></range>
</package>
</affects>
<description>
- ${DESC_BODY}
+ ${DESC_BODY}
</description>
<references>
<cvename>${cvename}</cvename>
<url>${cveurl}</url>
</references>
<dates>
- <discovery>${discovery}</discovery>
- <entry>${entry}</entry>
+ <discovery>${discovery_date}</discovery>
+ <entry>${entry_date}</entry>
</dates>
</vuln>
diff --git a/security/vuxml/files/nvd_provider.sh b/security/vuxml/files/nvd_provider.sh
new file mode 100644
--- /dev/null
+++ b/security/vuxml/files/nvd_provider.sh
@@ -0,0 +1,72 @@
+# Provider for the National Vulnerability Database
+# https://nvd.nist.gov/
+
+tmp_nvd=""
+
+init_nvd()
+{
+ tmp_nvd=$(mktemp "${TMPDIR:-/tmp}"/nvd_json_data.XXXXXXXXXX) || exit 1
+ fetch -q -o "${tmp_nvd}" https://services.nvd.nist.gov/rest/json/cves/2.0?cveId="${CVE_ID}" || exit 1
+}
+
+cleanup_nvd()
+{
+ rm "${tmp_nvd}" 2>/dev/null
+}
+
+get_cvename_from_nvd()
+{
+ cvename="${CVE_ID}"
+ echo "${cvename}"
+}
+
+get_cveurl_from_nvd() {
+ cveurl=https://nvd.nist.gov/vuln/detail/${CVE_ID}
+ echo "${cveurl}"
+}
+
+get_details_from_nvd() {
+ pref=".vulnerabilities[0].cve"
+ jq -r "${pref}.descriptions[0].value|@html" "${tmp_nvd}" | fmt -p -s | sed '1!s/^/\t/'
+}
+
+get_discovery_date_from_nvd() {
+ pref=".vulnerabilities[0].cve"
+ jq -r "${pref}.published|@html" "${tmp_nvd}" | cut -f1 -dT
+}
+
+get_entry_date_from_nvd() {
+ echo "${entry_date}"
+}
+
+get_product_name_from_nvd() {
+ jq -r ' .vulnerabilities[].cve.configurations[].nodes[].cpeMatch[] |
+ "((.criteria | split(":")[4]))" ' "${tmp_nvd}"
+}
+
+get_product_range_from_nvd() {
+ jq -r ' .vulnerabilities[]?.cve.configurations[]?.nodes[]?.cpeMatch[]?.versionEndExcluding ' "${tmp_nvd}"
+}
+
+get_package_name_from_nvd() {
+ jq -r '.vulnerabilities[].cve.configurations[].nodes[].cpeMatch[0].criteria' "${tmp_nvd}" | cut -f5 -d:
+}
+
+get_references_from_nvd() {
+ pref=".vulnerabilities[0].cve.references[0]"
+ jq -r "${pref}.url|@html" "${tmp_nvd}" | tr " " "\n"
+}
+
+get_source_from_nvd()
+{
+ pref=".vulnerabilities[0].cve.references[0]"
+ jq -r "${pref}.source|@html" "${tmp_nvd}" | tr " " "\n"
+}
+
+get_topic_from_nvd() {
+ # NVD does not provide a nice summary. Let's use the first sentence from
+ # the details instead
+ pref=".vulnerabilities[0].cve"
+ jq -r "${pref}.descriptions[0].value|@html" "${tmp_nvd}" | cut -f1 -d.
+}
+
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 20, 8:38 PM (15 h, 33 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31863311
Default Alt Text
D52903.id163529.diff (13 KB)
Attached To
Mode
D52903: security/vuxml: Improve newentry
Attached
Detach File
Event Timeline
Log In to Comment