Skip to content

Commit c60c2d0

Browse files
committed
advisory: gen-advisory CSAF 2.0 + CycloneDX VEX generator + make target
Generate CSAF 2.0 advisories and CycloneDX 1.6 VEX from wolfSSL CVE Program records plus a human-authored VEX overlay (state/justification, fixed versions, separate FIPS product, reachability hedge). Stdlib-only, SOURCE_DATE_EPOCH-reproducible, mirroring scripts/gen-sbom. `make advisory` is a thin wrapper around the same script and is interchangeable with it: both default to the canonical advisories/ tree (advisories/records/*.json + advisories/vex-overlay.json) and, with no record arguments, emit one CSAF + one CycloneDX document per CVE into advisories/out/ (a build artefact, gitignored). Explicit --cve-record/--csaf-out/--cdx-vex-out still drive single or bundled per-release documents. CSAF 2.0 scores[] carry only CVSS v2/v3 (the schema predates v4); a v4-only finding is preserved as a note plus aggregate_severity, with the machine-readable v4 rating in the CycloneDX output. CWE names are resolved from the official catalogue (cwe-names.json) for CSAF 6.1.11. The overlay format is documented by advisory-vex-overlay.example.json and constrained by advisory-vex-overlay.schema.json. Signed-off-by: Sameeh Jubran <sameeh@wolfssl.com>
1 parent fa04f70 commit c60c2d0

10 files changed

Lines changed: 2330 additions & 0 deletions

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ ctaocrypt/src/src/
2020
/_sbom_staging/
2121
/_bomsh.conf
2222
/bomsh_raw_logfile*
23+
24+
# Generated advisory documents (produced by `make advisory` /
25+
# `scripts/gen-advisory`). Inputs under advisories/records/ and
26+
# advisories/vex-overlay.json are tracked; the generated out/ tree is not.
27+
/advisories/out/
28+
29+
# Node deps pulled in only by the CSAF conformance check
30+
# (scripts/csaf_validate.mjs uses @secvisogram/csaf-validator-lib).
31+
/node_modules/
32+
/package-lock.json
2333
*.user
2434
!*-VS2022.vcxproj.user
2535
configure

Makefile.am

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,72 @@ uninstall-sbom:
490490

491491
CLEANFILES += $(SBOM_CDX) $(SBOM_SPDX) $(SBOM_SPDX_TV)
492492

493+
# Security advisory generation (CSAF 2.0 + CycloneDX 1.6 VEX)
494+
#
495+
# `make advisory` is a thin wrapper around scripts/gen-advisory: it feeds the
496+
# script the canonical advisory single-source-of-truth under advisories/ and is
497+
# byte-for-byte interchangeable with running the script by hand. Equivalent
498+
# invocations:
499+
#
500+
# make advisory
501+
# python3 scripts/gen-advisory # uses the same defaults
502+
# python3 scripts/gen-advisory \
503+
# --records-dir advisories/records \
504+
# --vex-overlay advisories/vex-overlay.json \
505+
# --out-dir advisories/out
506+
#
507+
# Inputs (tracked in git): advisories/records/CVE-*.json + advisories/vex-overlay.json
508+
# Outputs (build artifacts): advisories/out/CVE-*.{csaf,cdx}.json
509+
ADVISORY_RECORDS_DIR = $(srcdir)/advisories/records
510+
ADVISORY_OVERLAY = $(srcdir)/advisories/vex-overlay.json
511+
ADVISORY_OUT_DIR = $(abs_builddir)/advisories/out
512+
advisorydir = $(datadir)/doc/$(PACKAGE)/advisories
513+
514+
.PHONY: advisory install-advisory uninstall-advisory
515+
516+
# Generate one CSAF + one CycloneDX VEX document per CVE record. Honors
517+
# SOURCE_DATE_EPOCH for reproducible output (set from the last git commit when
518+
# unset and a git tree is available), exactly like `make sbom`.
519+
advisory:
520+
@if test -z "$(PYTHON3)"; then \
521+
echo ""; \
522+
echo "ERROR: 'python3' not found in PATH. Cannot generate advisories."; \
523+
echo ""; \
524+
exit 1; \
525+
fi
526+
@set -e; \
527+
if test -z "$${SOURCE_DATE_EPOCH:-}" && test -n "$(GIT)" && \
528+
$(GIT) -C "$(srcdir)" rev-parse --git-dir >/dev/null 2>&1; then \
529+
sde=`$(GIT) -C "$(srcdir)" log -1 --format=%ct 2>/dev/null`; \
530+
if test -n "$$sde"; then \
531+
SOURCE_DATE_EPOCH="$$sde"; \
532+
export SOURCE_DATE_EPOCH; \
533+
fi; \
534+
fi; \
535+
$(PYTHON3) $(srcdir)/scripts/gen-advisory \
536+
--records-dir $(ADVISORY_RECORDS_DIR) \
537+
--vex-overlay $(ADVISORY_OVERLAY) \
538+
--out-dir $(ADVISORY_OUT_DIR)
539+
540+
install-advisory: advisory
541+
$(MKDIR_P) $(DESTDIR)$(advisorydir)
542+
@for f in $(ADVISORY_OUT_DIR)/*.json; do \
543+
echo " $(INSTALL_DATA) $$f $(DESTDIR)$(advisorydir)/"; \
544+
$(INSTALL_DATA) "$$f" $(DESTDIR)$(advisorydir)/; \
545+
done
546+
547+
uninstall-advisory:
548+
-rm -f $(DESTDIR)$(advisorydir)/*.csaf.json
549+
-rm -f $(DESTDIR)$(advisorydir)/*.cdx.json
550+
551+
CLEANFILES += advisories/out/*.csaf.json advisories/out/*.cdx.json
552+
553+
# Ship the advisory generator inputs in the dist tarball so a downstream
554+
# consumer can `./configure && make advisory` from a release.
555+
EXTRA_DIST += advisories/records/CVE-2026-5501.json \
556+
advisories/records/CVE-2026-5778.json \
557+
advisories/vex-overlay.json
558+
493559
# Bomsh (OmniBOR build artifact tracing + SBOM enrichment)
494560
BOMSH_RAWLOG_BASE = $(abs_builddir)/bomsh_raw_logfile
495561
BOMSH_RAWLOG = $(BOMSH_RAWLOG_BASE).sha1
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{
2+
"dataType": "CVE_RECORD",
3+
"dataVersion": "5.2",
4+
"cveMetadata": {
5+
"cveId": "CVE-2026-5501",
6+
"assignerOrgId": "50d2cd11-d01a-48ed-9441-5bfce9d63b27",
7+
"state": "PUBLISHED",
8+
"assignerShortName": "wolfSSL",
9+
"dateReserved": "2026-04-03T15:46:09.302Z",
10+
"datePublished": "2026-04-10T03:07:39.604Z",
11+
"dateUpdated": "2026-04-22T13:59:28.514Z"
12+
},
13+
"containers": {
14+
"cna": {
15+
"providerMetadata": {
16+
"orgId": "50d2cd11-d01a-48ed-9441-5bfce9d63b27",
17+
"shortName": "wolfSSL",
18+
"dateUpdated": "2026-04-10T03:07:39.604Z"
19+
},
20+
"title": "Improper Certificate Signature Verification in X.509 Chain Validation Allows Forged Leaf Certificates",
21+
"problemTypes": [
22+
{
23+
"descriptions": [
24+
{
25+
"lang": "en",
26+
"cweId": "CWE-295",
27+
"description": "CWE-295 Improper certificate validation",
28+
"type": "CWE"
29+
}
30+
]
31+
}
32+
],
33+
"affected": [
34+
{
35+
"vendor": "wolfSSL",
36+
"product": "wolfSSL",
37+
"modules": [
38+
"wolfSSL_X509_verify_cert"
39+
],
40+
"programFiles": [
41+
"src/x509_str.c"
42+
],
43+
"versions": [
44+
{
45+
"status": "affected",
46+
"version": "0",
47+
"lessThanOrEqual": "5.9.0",
48+
"versionType": "semver"
49+
}
50+
],
51+
"defaultStatus": "unaffected"
52+
}
53+
],
54+
"descriptions": [
55+
{
56+
"lang": "en",
57+
"value": "wolfSSL_X509_verify_cert in the OpenSSL compatibility layer accepts a certificate chain in which the leaf's signature is not checked, if the attacker supplies an untrusted intermediate with Basic Constraints `CA:FALSE` that is legitimately signed by a trusted root. An attacker who obtains any leaf certificate from a trusted CA (e.g. a free DV cert from Let's Encrypt) can forge a certificate for any subject name with any public key and arbitrary signature bytes, and the function returns `WOLFSSL_SUCCESS` / `X509_V_OK`. The native wolfSSL TLS handshake path (`ProcessPeerCerts`) is not susceptible and the issue is limited to applications using the OpenSSL compatibility API directly, which would include integrations of wolfSSL into nginx and haproxy.",
58+
"supportingMedia": [
59+
{
60+
"type": "text/html",
61+
"base64": false,
62+
"value": "wolfSSL_X509_verify_cert in the OpenSSL compatibility layer accepts a certificate chain in which the leaf's signature is not checked, if the attacker supplies an untrusted intermediate with Basic Constraints `CA:FALSE` that is legitimately signed by a trusted root. An attacker who obtains any leaf certificate from a trusted CA (e.g. a free DV cert from Let's Encrypt) can forge a certificate for any subject name with any public key and arbitrary signature bytes, and the function returns `WOLFSSL_SUCCESS` / `X509_V_OK`. The native wolfSSL TLS handshake path (`ProcessPeerCerts`) is not susceptible and the issue is limited to applications using the OpenSSL compatibility API directly, which would include integrations of wolfSSL into nginx and haproxy."
63+
}
64+
]
65+
}
66+
],
67+
"references": [
68+
{
69+
"url": "https://github.com/wolfSSL/wolfssl/pull/10102"
70+
}
71+
],
72+
"metrics": [
73+
{
74+
"format": "CVSS",
75+
"scenarios": [
76+
{
77+
"lang": "en",
78+
"value": "GENERAL"
79+
}
80+
],
81+
"cvssV4_0": {
82+
"attackVector": "NETWORK",
83+
"attackComplexity": "LOW",
84+
"attackRequirements": "NONE",
85+
"privilegesRequired": "LOW",
86+
"userInteraction": "NONE",
87+
"vulnConfidentialityImpact": "HIGH",
88+
"subConfidentialityImpact": "NONE",
89+
"vulnIntegrityImpact": "HIGH",
90+
"subIntegrityImpact": "NONE",
91+
"vulnAvailabilityImpact": "NONE",
92+
"subAvailabilityImpact": "NONE",
93+
"exploitMaturity": "NOT_DEFINED",
94+
"Safety": "NOT_DEFINED",
95+
"Automatable": "NOT_DEFINED",
96+
"Recovery": "NOT_DEFINED",
97+
"valueDensity": "NOT_DEFINED",
98+
"vulnerabilityResponseEffort": "NOT_DEFINED",
99+
"providerUrgency": "NOT_DEFINED",
100+
"version": "4.0",
101+
"baseSeverity": "HIGH",
102+
"baseScore": 8.6,
103+
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N"
104+
}
105+
}
106+
],
107+
"credits": [
108+
{
109+
"lang": "en",
110+
"value": "Calif.io in collaboration with Claude and Anthropic Research",
111+
"type": "finder"
112+
}
113+
],
114+
"source": {
115+
"discovery": "EXTERNAL"
116+
},
117+
"x_generator": {
118+
"engine": "Vulnogram 1.0.1"
119+
}
120+
}
121+
}
122+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{
2+
"dataType": "CVE_RECORD",
3+
"dataVersion": "5.2",
4+
"cveMetadata": {
5+
"cveId": "CVE-2026-5778",
6+
"assignerOrgId": "50d2cd11-d01a-48ed-9441-5bfce9d63b27",
7+
"state": "PUBLISHED",
8+
"assignerShortName": "wolfSSL",
9+
"dateReserved": "2026-04-08T08:25:15.400Z",
10+
"datePublished": "2026-04-09T21:45:09.053Z",
11+
"dateUpdated": "2026-04-10T13:53:29.181Z"
12+
},
13+
"containers": {
14+
"cna": {
15+
"providerMetadata": {
16+
"orgId": "50d2cd11-d01a-48ed-9441-5bfce9d63b27",
17+
"shortName": "wolfSSL",
18+
"dateUpdated": "2026-04-09T21:45:09.053Z"
19+
},
20+
"title": "Integer underflow leads to out-of-bounds access in sniffer ChaCha decrypt path.",
21+
"problemTypes": [
22+
{
23+
"descriptions": [
24+
{
25+
"lang": "en",
26+
"cweId": "CWE-191",
27+
"description": "CWE-191 Integer underflow (wrap or wraparound)",
28+
"type": "CWE"
29+
}
30+
]
31+
}
32+
],
33+
"affected": [
34+
{
35+
"vendor": "wolfSSL",
36+
"product": "wolfSSL",
37+
"modules": [
38+
"Packet sniffer"
39+
],
40+
"programFiles": [
41+
"src/sniffer.c"
42+
],
43+
"versions": [
44+
{
45+
"status": "affected",
46+
"version": "0",
47+
"lessThanOrEqual": "5.9.0",
48+
"versionType": "semver"
49+
}
50+
],
51+
"defaultStatus": "unaffected"
52+
}
53+
],
54+
"descriptions": [
55+
{
56+
"lang": "en",
57+
"value": "Integer underflow in wolfSSL packet sniffer <= 5.9.0 allows an attacker to cause a program crash in the AEAD decryption path by injecting a TLS record shorter than the explicit IV plus authentication tag into traffic inspected by ssl_DecodePacket. The underflow wraps a 16-bit length to a large value that is passed to AEAD decryption routines, causing a large out-of-bounds read and crash. An unauthenticated attacker can trigger this remotely via malformed TLS Application Data records.",
58+
"supportingMedia": [
59+
{
60+
"type": "text/html",
61+
"base64": false,
62+
"value": "Integer underflow in wolfSSL packet sniffer &lt;= 5.9.0 allows an attacker to cause a program crash in the AEAD decryption path by injecting a TLS record shorter than the explicit IV plus authentication tag into traffic inspected by ssl_DecodePacket. The underflow wraps a 16-bit length to a large value that is passed to AEAD decryption routines, causing a large out-of-bounds read and crash. An unauthenticated attacker can trigger this remotely via malformed TLS Application Data records."
63+
}
64+
]
65+
}
66+
],
67+
"references": [
68+
{
69+
"url": "https://github.com/wolfSSL/wolfssl/pull/10125"
70+
}
71+
],
72+
"metrics": [
73+
{
74+
"format": "CVSS",
75+
"scenarios": [
76+
{
77+
"lang": "en",
78+
"value": "GENERAL"
79+
}
80+
],
81+
"cvssV4_0": {
82+
"attackVector": "NETWORK",
83+
"attackComplexity": "LOW",
84+
"attackRequirements": "PRESENT",
85+
"privilegesRequired": "LOW",
86+
"userInteraction": "PASSIVE",
87+
"vulnConfidentialityImpact": "NONE",
88+
"subConfidentialityImpact": "NONE",
89+
"vulnIntegrityImpact": "NONE",
90+
"subIntegrityImpact": "NONE",
91+
"vulnAvailabilityImpact": "LOW",
92+
"subAvailabilityImpact": "NONE",
93+
"exploitMaturity": "NOT_DEFINED",
94+
"Safety": "NOT_DEFINED",
95+
"Automatable": "NOT_DEFINED",
96+
"Recovery": "NOT_DEFINED",
97+
"valueDensity": "NOT_DEFINED",
98+
"vulnerabilityResponseEffort": "NOT_DEFINED",
99+
"providerUrgency": "NOT_DEFINED",
100+
"version": "4.0",
101+
"baseSeverity": "LOW",
102+
"baseScore": 2.1,
103+
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N"
104+
}
105+
}
106+
],
107+
"credits": [
108+
{
109+
"lang": "en",
110+
"value": "Zou Dikai",
111+
"type": "finder"
112+
}
113+
],
114+
"source": {
115+
"discovery": "EXTERNAL"
116+
},
117+
"x_generator": {
118+
"engine": "Vulnogram 1.0.1"
119+
}
120+
}
121+
}
122+
}

advisories/vex-overlay.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"_comment": "Canonical wolfSSL VEX overlay consumed by `make advisory` / `scripts/gen-advisory`. Keyed by CVE id; carries the determinations the CVE Program record cannot express (analysis state, justification, fixed versions, remediation, optional FIPS product, optional build-reachability hedge). Constrained by scripts/advisory-vex-overlay.schema.json. To model a wolfCrypt FIPS module as a separate product, add a \"fips\" block per the format in scripts/advisory-vex-overlay.example.json using the real validated module version and CMVP certificate number (do NOT copy the illustrative placeholder values from the example).",
3+
4+
"CVE-2026-5501": {
5+
"state": "exploitable",
6+
"response": ["update"],
7+
"detail": "Limited to applications using the OpenSSL compatibility API directly (wolfSSL_X509_verify_cert), such as nginx and haproxy integrations. The native wolfSSL TLS handshake path (ProcessPeerCerts) is not susceptible.",
8+
"fixed_versions": ["5.9.1"],
9+
"remediation": "Update to wolfSSL 5.9.1 or later, or avoid relying on wolfSSL_X509_verify_cert in the OpenSSL compatibility layer for chain validation."
10+
},
11+
12+
"CVE-2026-5778": {
13+
"state": "exploitable",
14+
"response": ["update"],
15+
"detail": "Integer underflow in the ChaCha20-Poly1305 decryption path of the packet sniffer.",
16+
"requires_defines": ["WOLFSSL_SNIFFER", "HAVE_CHACHA", "HAVE_POLY1305"],
17+
"default_status": "off",
18+
"fixed_versions": ["5.9.1"],
19+
"remediation": "Update to wolfSSL 5.9.1 or later. Builds without --enable-sniffer are not affected."
20+
}
21+
}

0 commit comments

Comments
 (0)