#! /bin/sh
set -eu
vuxml_file="$1"
CVE_ID=""
SA_ID=""
show_usage() {
exec >&2
echo "Usage: newentry.sh /path/to/vuxml/document [CVE_ID|SA_ID]"
exit 1
}
if [ -z "${vuxml_file}" ]; then
show_usage
fi
# -----------------
# Process arguments
# -----------------
shift
while [ $# -gt 0 ]; do
case "$1" in
CVE_ID=*)
CVE_ID="${1#CVE_ID=}"
shift
;;
SA_ID=*)
SA_ID="${1#SA_ID=}"
shift
;;
*)
echo "Invalid argument: $1"
show_usage
exit 1
;;
esac
done
tmp=$(mktemp "${TMPDIR:-/tmp}"/vuxml.XXXXXXXXXX) || exit 1
tmp_fbsd_sa=""
# -------------------------------------
# Define how to clean up temporal files
# -------------------------------------
#
doclean="yes"
cleanup() {
if [ "${doclean}" = "yes" ]; then
rm -f "${tmp}" "${tmp_fbsd_sa}" > /dev/null
fi
# Call cleaners for providers
for provider in ${valid_providers}; do
cleanup_"${provider}"
cleanup_"${provider}"
done
}
trap cleanup EXIT HUP INT PIPE TERM
# -----------------------------
# 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="$(date -u '+%Y-%m')-FIXME" || exit 1
entry_date="$(date -u '+%Y-%m-%d')" || exit 1
package_name=""
product_name=""
product_range=""
package_list="
${source} reports:
" # -------------------------------- # 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 } # ------------------------------------------ # List of CVE providers sorted by preference # ------------------------------------------ providers="mitre nvd euvd" valid_providers="" # ------------------------------------------ # 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 ${valid_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 in provider ${provider}" fi done echo "null" } # -------------------------------------------------- # Fill global variables with data from CVE databases # -------------------------------------------------- get_cve_info() { for field in ${fields}; do value=$(resolve_field "${field}" ${valid_providers}) eval "${field}=\$value" done DESC_BODY="${details}
${source} reports:
" } # ---------------------------------------------------------------- # 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 # Create variables from SA note if grep -q 'CVE Name' "${tmp_fbsd_sa}"; then cve_tmp=$(grep 'CVE Name' "${tmp_fbsd_sa}" | cut -f2 -d:) || exit 1 cvename="${cve_tmp#"${cve_tmp%%[![:space:]]*}"}" # NVD database only accepts uppercase CVE ids, like CVE-2022-39282, NOT # cve-2022-39282. cvename=$(echo "${cvename}" | tr '[:lower:]' '[:upper:]') || exit 1 cveurl="https://nvd.nist.gov/vuln/detail/${cvename}" fi details=$(awk '/II. Problem Description/ {f=1;next;next} /III. Impact/ {f=0} (f==1) {print}' "${tmp_fbsd_sa}" ) || exit 1 details=$(echo "${details}
${details}
" | fmt -p -s | sed -e 's//
/' | sed '1!s/^/\t/') impact=$(awk '/III. Impact/ {f=1;next;next} /IV. Workaround/ {f=0} (f==1) {print}' "${tmp_fbsd_sa}") || exit 1 impact=$(echo "
${impact}
" | fmt -p -s | sed -e 's//
/' | sed '1!s/^/\t/') package_name="FreeBSD" if grep -Eq 'Module:.*kernel' "${tmp_fbsd_sa}"; then package_name="${package_name}-kernel" fi upstream_fix="FIXME" references="${SA_URL_BASE}${SA_ID}" source="The FreeBSD Project" topic_tmp=$(grep 'Topic:' "${tmp_fbsd_sa}" | cut -f2 -d:) || exit 1 topic="${topic_tmp#"${topic_tmp%%[![:space:]]*}"}" DESC_BODY="