CVE-2022-43996
Description
The csaf_provider package before 0.8.2 allows XSS via a crafted CSAF document uploaded as text/html. The endpoint upload allows valid CSAF advisories (JSON format) to be uploaded with Content-Type text/html and filenames ending in .html. When subsequently accessed via web browser, these advisories are served and interpreted as HTML pages. Such uploaded advisories can contain JavaScript code that will execute within the browser context of users inspecting the advisory.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CSAF provider before 0.8.2 allows stored XSS via uploaded CSAF advisories with Content-Type text/html and .html extension.
Vulnerability
Overview
The csaf_provider package, part of the csaf_distribution tools [4], contains a stored cross-site scripting (XSS) vulnerability in versions before 0.8.2. The upload endpoint accepts valid CSAF advisories in JSON format but fails to validate the Content-Type header and filename extension. An attacker can upload a CSAF document with Content-Type: text/html and a filename ending in .html, causing the server to serve the advisory as an HTML page [1].
Exploitation
No authentication is required to upload a CSAF document to the provider's management endpoint. An attacker crafts a valid CSAF advisory (JSON structure that passes schema validation) and includes malicious JavaScript within the advisory content. The file is uploaded with the text/html MIME type and an .html extension. When other users (e.g., security analysts, administrators) view the uploaded advisory through their web browser, the server returns the file with an HTML content type, and the browser renders it as a web page, executing the embedded JavaScript [1].
Impact
Successful exploitation allows an attacker to execute arbitrary JavaScript in the context of the victim's browser session on the CSAF provider domain. This can lead to theft of session cookies, exfiltration of sensitive data displayed on the page, or performing actions on behalf of the authenticated user. The vulnerability is classified as stored XSS because the malicious payload persists on the server and affects all subsequent viewers of the advisory [1].
Mitigation
The vulnerability is fixed in csaf_provider version 0.8.2 [3]. The fix introduces a filename conformity check that rejects uploaded files whose names do not conform to the CSAF standard for advisory filenames (e.g., requiring the .json extension) [2]. Users should upgrade to csaf_provider 0.8.2 or later. There are no known workarounds; ensuring the upload endpoint is not exposed to untrusted users may reduce risk but does not eliminate it.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/csaf-poc/csaf_distributionGo | < 0.8.2 | 0.8.2 |
Affected products
3- csaf_provider/csaf_providerdescription
- Range: <0.8.2
Patches
117f22855ee8dAdd filename conformity check
6 files changed · +100 −10
cmd/csaf_aggregator/mirror.go+7 −1 modified@@ -419,7 +419,13 @@ func (w *worker) mirrorFiles(tlpLabel *csaf.TLPLabel, files []string) error { log.Printf("error: %s\n", err) continue } - filename := util.CleanFileName(filepath.Base(u.Path)) + + // Ignore not confirming filenames. + filename := filepath.Base(u.Path) + if !util.ConfirmingFileName(filename) { + log.Printf("Not confirming filename %q. Ignoring.\n", filename) + continue + } var advisory interface{}
cmd/csaf_checker/processor.go+25 −1 modified@@ -22,6 +22,7 @@ import ( "log" "net/http" "net/url" + "path/filepath" "regexp" "sort" "strconv" @@ -204,6 +205,7 @@ func (p *processor) checkDomain(domain string) error { (*processor).checkSecurity, (*processor).checkCSAFs, (*processor).checkMissing, + (*processor).checkInvalid, (*processor).checkListing, (*processor).checkWellknownMetadataReporter, (*processor).checkDNSPathReporter, @@ -724,7 +726,29 @@ func (p *processor) checkMissing(string) error { return nil } -// checkListing wents over all found adivisories URLs and checks, +// checkInvalid wents over all found adivisories URLs and checks +// if file name confirms to standard. +func (p *processor) checkInvalid(string) error { + + p.badDirListings.use() + var invalids []string + + for f := range p.alreadyChecked { + if !util.ConfirmingFileName(filepath.Base(f)) { + invalids = append(invalids, f) + } + } + + if len(invalids) > 0 { + sort.Strings(invalids) + p.badDirListings.add("advisories with invalid file names: %s", + strings.Join(invalids, ", ")) + } + + return nil +} + +// checkListing wents over all found adivisories URLs and checks // if their parent directory is listable. func (p *processor) checkListing(string) error {
cmd/csaf_provider/actions.go+4 −0 modified@@ -39,6 +39,10 @@ func (c *controller) loadCSAF(r *http.Request) (string, []byte, error) { } defer file.Close() + if !util.ConfirmingFileName(handler.Filename) { + return "", nil, errors.New("given csaf filename is not confirming") + } + var buf bytes.Buffer if _, err := io.Copy(&buf, c.cfg.uploadLimiter(file)); err != nil { return "", nil, err
cmd/csaf_uploader/main.go+4 −0 modified@@ -277,6 +277,10 @@ func (p *processor) uploadRequest(filename string) (*http.Request, error) { // It prints the response messages. func (p *processor) process(filename string) error { + if bn := filepath.Base(filename); !util.ConfirmingFileName(bn) { + return fmt.Errorf("%q is not a confirming file name", bn) + } + req, err := p.uploadRequest(filename) if err != nil { return err
util/file.go+18 −8 modified@@ -19,15 +19,25 @@ import ( "time" ) -var ( - twoOrMoreDots = regexp.MustCompile(`\.{2,}`) - stripSlashes = strings.NewReplacer(`/`, ``, `\`, ``) -) - -// CleanFileName removes the "/" "\" charachters and replace the two or more -// occurences of "." with only one from the passed string. +var invalidRune = regexp.MustCompile(`[^+\-a-z0-9]+`) // invalid runes + `_` + +// CleanFileName replaces invalid runes with an underscore and +// afterwards collapses multiple underscores into one. +// If the filename does not end with '.json' it will be appended. +// The filename is converted to lower case. +// https://docs.oasis-open.org/csaf/csaf/v2.0/csd02/csaf-v2.0-csd02.html#51-filename +// specifies valid runes as 'a' to 'z', '0' to '9' and '+', '-', '_'. func CleanFileName(s string) string { - return twoOrMoreDots.ReplaceAllString(stripSlashes.Replace(s), `.`) + s = strings.ToLower(s) + if strings.HasSuffix(s, ".json") { + s = s[:len(s)-len(".json")] + } + return invalidRune.ReplaceAllString(s, "_") + ".json" +} + +// ConfirmingFileName checks if the given filename is confirming the standard. +func ConfirmingFileName(fname string) bool { + return fname == CleanFileName(fname) } // PathExists returns true if path exits.
util/file_test.go+42 −0 modified@@ -5,6 +5,48 @@ import ( "testing" ) +func TestCleanFileName(t *testing.T) { + for _, x := range [][2]string{ + {`HELLO`, `hello.json`}, + {`hello`, `hello.json`}, + {`cisco-sa-20190513-secureboot.json`, `cisco-sa-20190513-secureboot.json`}, + {``, `.json`}, + {`..`, `_.json`}, + {`../..`, `_.json`}, + {`abc.html`, `abc_html.json`}, + {`abc_.htm__l`, `abc_htm_l.json`}, + {`foo+BAR`, `foo+bar.json`}, + } { + if got := CleanFileName(x[0]); got != x[1] { + t.Errorf("%q: Expected %q but got %q.", x[0], x[1], got) + } + } +} + +func TestConfirmingFileName(t *testing.T) { + for _, x := range []struct { + s string + b bool + }{ + {`HELLO`, false}, + {`hello`, false}, + {`cisco-sa-20190513-secureboot.json`, true}, + {`example_company_-_2019-yh3234.json`, true}, + {`rhba-2019_0024.json`, true}, + {`2022__01-a.json`, false}, + {``, false}, + {`..`, false}, + {`../..`, false}, + {`abc.html`, false}, + {`abc_.htm__l`, false}, + {`foo+BAR`, false}, + } { + if got := ConfirmingFileName(x.s); got != x.b { + t.Errorf("%q: Expected %t but got %t.", x.s, x.b, got) + } + } +} + func TestNWriter(t *testing.T) { msg := []byte("Gruß!\n")
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-xxfx-w2rw-gh63ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-43996ghsaADVISORY
- github.com/csaf-poc/csaf_distribution/commit/17f22855ee8d4270dd17ff748c30ed7304846fdcghsaWEB
- github.com/csaf-poc/csaf_distribution/releases/tag/v0.8.2ghsaWEB
- wid.cert-bund.de/.well-known/csaf/white/2022/bsi-2022-0003.jsonghsaWEB
News mentions
0No linked articles in our index yet.