Skip to content

CSAF-2.1: Failed Mandatory Test 6.1.26 #738

Closed

Description

@bendo-eXX

csaf-validator-lib/csaf_2_1/mandatoryTests/mandatoryTest_6_1_26.js (Test 6.1.26 "Prohibited Document Category Name") produces incorrect results for several official OASIS CSAF TC conformance test vectors shipped in csaf/csaf_2.1/test/validator/data/mandatory/:

Test file Expected Actual
oasis_csaf_tc-csaf_2_1-2024-6-1-26-15.json (csaf_vulnerability_report) valid invalid
oasis_csaf_tc-csaf_2_1-2024-6-1-26-09.json (Vulnerability_report) invalid valid
oasis_csaf_tc-csaf_2_1-2024-6-1-26-22.json (dash look-alikes) invalid valid
oasis_csaf_tc-csaf_2_1-2024-6-1-26-23.json (connector look-alikes) invalid valid
oasis_csaf_tc-csaf_2_1-2024-6-1-26-24.json (invisible characters) invalid valid

Root Causes

A) Missing 9th profile

allowedCategoryValues only lists the 8 profiles from earlier drafts and is missing
csaf_vulnerability_report (Profile 9 "Vulnerability Report", CSAF 2.1 spec §4.9).
This causes:

  • The legitimate value csaf_vulnerability_report to be flagged as using the
    reserved csaf_ prefix (false failure, -15).
  • The similarly-named value Vulnerability_report to not be recognized as a
    prohibited name collision (false pass, -09).

B) Incomplete Unicode separator coverage

SEPARATOR_PATTERN (/[\p{Dash}\p{Pc}\u0332\s]+/gu) is used to strip
dash/underscore/whitespace-like characters before comparing the category value
against profile names, per spec:

Any occurrences of dash, hyphen, minus, underscore, white space and invisible
characters are removed from the values on both sides before the case insensitive
match.

However, the test vectors -22, -23, -24 use dash-, connector-, and
invisible-character look-alikes that fall outside \p{Dash} / \p{Pc}, e.g.:

  • Box-drawing/technical dash symbols (\p{gc=So}, e.g. U+23AF, U+2500, U+2796)
  • A math symbol (\p{gc=Sm}, U+29FF)
  • A Duployan letter used purely as a visual underscore stand-in (\p{gc=Lo}, U+1BC86)
  • Format/invisible characters (\p{gc=Cf}, e.g. U+200B ZWSP, U+FEFF,
    U+2060 WORD JOINER) which aren't covered at all currently

Because these characters aren't stripped, the normalized string doesn't match the
prohibited profile name, so the check silently passes.

Proposed Solutions

Option A — Extend the pattern with explicit codepoints

Add \p{Cf} (covers all invisible-character cases) plus an explicit list of the
remaining dash-/connector-like codepoints not covered by any Unicode property
(derived directly from the official test vectors):

const SEPARATOR_PATTERN =
  /[\p{Dash}\p{Pc}\p{Cf}\u02D7\u02CD\u0332\u0333\u034F\u2017\u2043\u2053\u2581\u23AF\u23B5\u23BA\u23BB\u23BC\u23BD\u23E4\u2500\u2501\u254C\u254D\u2574\u2576\u2578\u257A\u2796\u29FF\u{1BC03}\u{1BC08}\u{1BC0D}\u{1BC11}\u{1BC12}\u{1BC13}\u{1BC86}\u{1BC96}\u{1BC97}\u{1BC99}\s]+/gu

Plus add 'csaf_vulnerability_report' to allowedCategoryValues.

Option B — Use a Unicode confusables (UTS #39) library

Use a "confusables skeleton" implementation (per
Unicode Technical Standard #39: Unicode Security Mechanisms,
e.g. npm packages confusables or unicode-confusables) to normalize look-alike
characters to their canonical form before comparison, instead of (or in addition to)
manual separator stripping.

Activity

  1. self-assigned this
    on Sep 22, 2026
  2. DevPhilB commented on Sep 22, 2026

    @DevPhilB
    Contributor

    We chose Option A for the following reasons:

    1. Scope match — Test 6.1.26 per spec is narrowly defined: strip dash, hyphen, minus, underscore, whitespace, and invisible characters, then do a case-insensitive comparison. It is not a general homoglyph/confusables check. A Unicode Technical Standard (UTS) Expose group of tests #39 confusables-skeleton library (Option B) solves a broader problem (e.g. Cyrillic "а" vs Latin "a") that isn't what this rule asks for, and it's unclear it would even correctly replicate the "strip specific character classes" semantics the spec requires without still needing manual separator stripping alongside it.
    2. No new dependency — Option A keeps the fix self-contained in the existing pattern-based approach the file already uses, avoiding the maintenance/security surface of an added package.
    3. Spec-confirmed root cause A — The CSAF 2.1 prose source (tests-01-mndtr-26-prohibited-document-category-name.md) explicitly lists csaf_vulnerability_report as one of the profile values the test must skip, confirming the 9th profile was simply missing from allowedCategoryValues.
    4. Auditable — Every added codepoint is traceable to a specific character used in an official test vector and documented inline (box-drawing/technical dash symbols, a math symbol, a Duployan letter, plus \p{Cf} for invisible/format characters), rather than relying on an opaque third-party confusables table whose behavior for this specific character set isn't guaranteed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions