{"$schema":"https://docs.oasis-open.org/csaf/csaf/v2.1/schema/csaf.json","document":{"category":"csaf_informational_advisory","csaf_version":"2.1","distribution":{"tlp":{"label":"CLEAR"}},"lang":"en","notes":[{"category":"summary","text":"ndaal_public_nvulnlookup 0.1.48 is a hardening + reorganization release with four user-visible items. (1) The CWE dashboard has moved from `/dashboards/cwe` to `/attacks/cwe` under a new Attacks navbar dropdown (immediately after CAPEC), grouping every attack/weakness-pattern catalog under a single menu (CAPEC, CWE, MITRE ATT&CK Enterprise / ICS / Mobile, MITRE EMB3D); all three legacy CWE page paths now serve HTTP 308 Permanent Redirect to their `/attacks/cwe*` equivalents, so existing links and bookmarks survive unchanged. The `/api/v1/cwe/*` API namespace is intentionally NOT moved (matches the prior CAPEC relocation precedent). (2) The cryptographic-hash sidecar contract for every release artefact is now five orthogonal families covering four cryptographic constructions across three independent designs: SHA-2 (Merkle–Damgård), SHA-3 (Keccak sponge), BLAKE3 (tree hash), and SHAKE256 (extendable-output function). Both `vulnerability-lookup-rs/release/create_release.sh` and `vulnerability-lookup-rs/scripts/update_ansible_role.sh` emit the full set; a new idempotent + recompute-and-compare-verifying `backfill_5sidecar_contract.{sh,bats}` tool retroactively brought every release artefact from v0.1.31 through v0.1.48 and the Ansible role files up to the contract (315 new `.blake3-512` + 315 new `.shake256-512` per-file sidecars + 34 new aggregate manifests landed in this release). (3) A new `test_ndaal_binsec` quality gate runs the ndaal-binsec fork (native validated SARIF 2.1.0 + Markdown output) across every shipped release binary, complementing the existing upstream-binsec gate. (4) Five pre-existing structural bugs cleared in the `verify_static_assets_{molecule,debian13}.sh` screenshot/Ansible verify pipelines so they finally run end-to-end against a fresh Vagrant box and the six Molecule (Podman) container distributions."},{"category":"description","text":"Detail per area:\n\n1. CWE → Attacks dashboard relocation:\n   * New canonical URLs: `/attacks/cwe`, `/attacks/cwe/recent/partial`, `/attacks/cwe/cwe/{id}`.\n   * Legacy redirects (308 Permanent Redirect, body-preserving, method-preserving): `/dashboards/cwe*` → `/attacks/cwe*`.  Three new handlers in `crates/vl-web/src/redirects.rs`; the per-CWE-id handler re-validates the id through `canonicalise_cwe_id` before splicing it into the Location header so the redirect target can only ever be `/attacks/cwe/cwe/CWE-<digits>` (no header injection or open-redirect from an attacker-controlled segment).\n   * Navbar reorganization: CWE moved out of the Dashboards dropdown into the new Attacks dropdown alongside CAPEC, MITRE ATT&CK Enterprise / ICS / Mobile, and MITRE EMB3D — a single grouping for every attack-pattern / weakness-pattern catalog.\n   * API namespace unchanged: `/api/v1/cwe/{key}` (allowlisted-key data endpoint) and `/api/v1/cwe/definition/{id}` (per-CWE definition drill-down) stay put — matches the prior CAPEC relocation precedent.\n   * Internal references aligned: page + pagination + detail templates, Bruno collection, API reference implementation + its pytest suite, testssl endpoint list, rust integration tests (now assert legacy paths return 308), both README mirrors + the Administrator Guide.\n\n2. Five-family hash sidecar contract enforcement:\n   * `create_release.sh` extended from 3 → 5 sidecar emitters across all three sidecar sites (per-binary, per-tarball, per-package) + 3 → 5 aggregate `*SUMS.txt` manifests under `release/v<ver>/`.\n   * `update_ansible_role.sh` extended the same way in `write_checksums()`, plus its file-cleanup glob comment + per-role summary counter updated for the 5 sidecar suffixes.\n   * `backfill_5sidecar_contract.sh` (new) walks both target trees, emits the two missing families wherever a `.sha-256` sidecar already exists, regenerates aggregate manifests where they are missing, and runs a phase-3 verify-everything sweep (recompute-and-compare each `.blake3-512` + `.shake256-512` against its target file; line-count cross-check against the sibling `SHA-256SUMS.txt`).  Existing sidecars are NEVER overwritten (timestamps + bytes preserved as an audit trail).  Self-skips gracefully when required tools (find, b3sum, python3 >= 3.6, sed) are missing.  36-test canonical bats sister.\n   * Backfill output committed in this release: 315 `.blake3-512` + 315 `.shake256-512` per-file sidecars + 34 aggregate manifests across `release/v0.1.31` through `release/v0.1.48` + `tools/ansible/roles/nvulnlookup/files/`.\n\n3. `test_ndaal_binsec` quality gate:\n   * Wired into `scripts/quality_gates.sh --full` (LIVE_GATES) immediately after the existing upstream `binsec` gate, so both detectors run on every release.\n   * Probes `binsec --help` for the `--format` flag set; self-skips with rc=0 when the on-PATH `binsec` is upstream (without the ndaal fork's native SARIF / Markdown output).\n   * When the ndaal-binsec fork IS on PATH, emits per-binary text + json + native validated SARIF 2.1.0 + Markdown reports plus aggregate JSON + jaq-derived SARIF roll-up under `documentation/security/binary/ndaal_binsec/ndaal_binsec_<TIMESTAMP>/`.  Per CLAUDE.md `skills/bash` canonical structure.  36-test canonical bats sister.\n\n4. Screenshot pipelines now cover the `/attacks` dropdown:\n   * Four scripts updated: `scripts/verify_static_assets_{molecule,debian13}.sh`, `scripts/create_screenshots_from_local_running_app.sh`, `vulnerability-lookup-rs/scripts/capture_screenshots.sh`.\n   * Each script now captures the six Attacks-menu entries: CAPEC, CWE, MITRE ATT&CK Enterprise / ICS / Mobile, MITRE EMB3D.\n   * Stale `/dashboards/cwe` capture rows removed in all four scripts (they would 308-redirect to `/attacks/cwe` and produce a duplicate with the wrong filename).\n\n5. `verify_static_assets_*` end-to-end bugfixes:\n   * mkdir-before-info bug: the molecule script's `preflight()` called `info` (which tee's to `${LOG_FILE}`) BEFORE the mkdir that creates the log dir — fixed by relocating the mkdir to the top of preflight.\n   * `parse_os_row()` IFS bug: under the script-wide `IFS=$'\\n\\t'` (no space), `pair=(${row})` against a space-separated matrix row produced a 1-element array and `${pair[1]}` tripped nounset — fixed with a local `IFS=' '`.\n   * Ansible UTF-8 locale: each `ansible-playbook` invocation now prefixes `LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8` (Ansible refuses to start under `C` locale; the strict-mode preamble exports `C` for the script's own helpers).\n   * Vault-password stub: both scripts now materialise a non-empty `${WORK_DIR}/.vault_password` and pass it via `ANSIBLE_VAULT_PASSWORD_FILE`, satisfying the repo-root ansible.cfg's `vault_password_file =` declaration without checking the file in.\n   * `capture_screenshots()` IFS bug: same `pair=(${row})` shape as parse_os_row at two sites — fixed with one function-scope `local IFS=' '`.\n\n6. Ansible role refresh: linux binaries refreshed to 0.1.48, 0.1.47 `.deb`/`.rpm` packages dropped (32 deletions), 0.1.48 packages added (32 new files + 5-family sidecars).  `nvulnlookup_version` default bumped 0.1.44 → 0.1.48 so the role's post-deploy version-check assertion passes.\n\n7. `update_ansible_cfg_project_specific.{sh,bats}` canonicalised per `skills/bash` + `skills/bats` (Bash >= 4.4 guard, canonical section-headers, `${0##*/}` anchors, mutation flags, `--help` short-circuit before side effects).  Bats sister: 27 → 36 tests against the canonical template; full pass.\n\n8. Two ancillary regression fixes: `test_inline_script_escape` repaired after the v0.1.43 nuclei pagination refactor removed the field the XSS-escape test was probing; `test_proptest`'s `collect_regressions()` was polluting its captured stdout with mutation-flag audit lines (broke `local -i nreg=$(...)`)."},{"category":"details","text":"Verification (0.1.48):\n  cargo check --workspace --all-features      # clean\n  cargo clippy -p vl-web --all-targets        # clean (rc=0)\n  cargo test -p vl-web --test test_inline_script_escape  # 9/9 pass\n  bats vulnerability-lookup-rs/scripts/backfill_5sidecar_contract.bats           # 36/36\n  bats vulnerability-lookup-rs/tests/scripts/test_ndaal_binsec.bats               # 36/36\n  bats scripts/update_ansible_cfg_project_specific.bats                          # 36/36\n  bash scripts/validate_csaf_documents.sh --root csaf/2026 --strict              # all advisories OK\n  bash vulnerability-lookup-rs/scripts/backfill_5sidecar_contract.sh             # 730 sidecars + 32 manifests verified, 0 failures in this release's new set\n\nLive verification (post-restart):\n  GET /attacks/cwe                            → 200\n  GET /dashboards/cwe                         → 308\n  GET /dashboards/cwe/recent/partial          → 308\n  GET /dashboards/cwe/cwe/79                  → 308\n  GET /attacks/cwe/cwe/79                     → 200\n  GET /attacks/capec                          → 200\n  GET /attacks/mitre-attack/enterprise        → 200\n  GET /attacks/mitre-attack/ics               → 200\n  GET /attacks/mitre-attack/mobile            → 200\n  GET /attacks/emb3d                          → 200\n  GET /api/v1/cwe/stats                       → 200\n\nUpgrade path: drop-in upgrade from 0.1.47.  No on-disk schema migration; the redb store keeps its existing format.  Operators have no manual action to take — bookmarks against the old `/dashboards/cwe` URLs receive a 308 redirect to the new `/attacks/cwe` URLs.  Downstream tooling that consumes `release/v<ver>/SHA-*SUMS.txt` keeps working unchanged; tooling that wants to take advantage of the new BLAKE3-512 / SHAKE256-512 manifests can pick them up from the matching `BLAKE3-512SUMS.txt` / `SHAKE256-512SUMS.txt` files."},{"category":"general","text":"Recommended action: upgrade to ndaal_public_nvulnlookup 0.1.48 or later.  The HTTP 308 redirects on the legacy `/dashboards/cwe*` paths are permanent, so dependent integrations that hard-code the old URLs will keep working through the redirect, but operators with the ability to update those integrations are encouraged to do so — strict CSAF-style consumers, link-rot scanners, and analytics dashboards generally prefer non-redirecting URLs.  No configuration change is required to receive the new BLAKE3-512 + SHAKE256-512 sidecars; both `create_release.sh` and `update_ansible_role.sh` emit them by default in the 0.1.48 build.  Operators who maintain their own release-artefact backups of pre-0.1.48 versions may use the new `backfill_5sidecar_contract.sh` to retroactively bring those backups up to the five-family contract — idempotent + recompute-and-compare verifying, never overwrites existing sidecars."},{"category":"other","text":"Severity classification: this is a hardening + reorganization release, NOT a security defect.  None of the items in this advisory document an exploitable issue in 0.1.47 or earlier; together they reduce attack surface (the 308-redirect with id-revalidation prevents open-redirect via the relocation), strengthen integrity guarantees (the five-family hash sidecar contract is defence-in-depth against a single-family cryptanalytic break), and remove operational footguns (the five `verify_static_assets_*` fixes enable end-to-end Ansible-role verification against fresh containers + VMs).  Status: final."},{"category":"legal_disclaimer","text":"THIS DOCUMENT IS PROVIDED ON AN 'AS IS' BASIS AND DOES NOT IMPLY ANY KIND OF GUARANTEE OR WARRANTY. ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS INFORMATION INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS."}],"publisher":{"category":"vendor","contact_details":"security@ndaal.eu","issuing_authority":"ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG Security Team","name":"ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG","namespace":"https://ndaal.eu/csaf"},"references":[{"category":"self","summary":"This advisory in CSAF 2.1 format","url":"https://gitlab.com/vPierre/ndaal_public_nvulnlookup/-/raw/main/csaf/2026/075/ndaal-sa-2026-075.json"},{"category":"external","summary":"ndaal_public_nvulnlookup 0.1.48 — CHANGELOG entry","url":"https://gitlab.com/vPierre/ndaal_public_nvulnlookup/-/blob/main/CHANGELOG.md"},{"category":"external","summary":"ndaal_public_nvulnlookup repository","url":"https://gitlab.com/vPierre/ndaal_public_nvulnlookup"},{"category":"external","summary":"ndaal-sa-2026-074 — ndaal_public_csaf_crud 0.3.4 release announcement (parallel 5-sidecar-contract enforcement on the sibling project)","url":"https://gitlab.com/vPierre/ndaal_public_nvulnlookup/-/raw/main/csaf/2026/074/ndaal-sa-2026-074.json"},{"category":"external","summary":"CWE — Common Weakness Enumeration (catalog now reachable at /attacks/cwe)","url":"https://cwe.mitre.org/"},{"category":"external","summary":"CAPEC — Common Attack Pattern Enumeration and Classification","url":"https://capec.mitre.org/"},{"category":"external","summary":"MITRE ATT&CK matrices (Enterprise / ICS / Mobile)","url":"https://attack.mitre.org/"},{"category":"external","summary":"MITRE EMB3D — Threat Model for Embedded Devices","url":"https://emb3d.mitre.org/"},{"category":"external","summary":"RFC 9110 §15.4.9 — HTTP 308 Permanent Redirect semantics","url":"https://www.rfc-editor.org/rfc/rfc9110.html#name-308-permanent-redirect"},{"category":"external","summary":"BLAKE3 cryptographic hash function","url":"https://github.com/BLAKE3-team/BLAKE3"},{"category":"external","summary":"FIPS 202 — SHA-3 / SHAKE256 specification","url":"https://csrc.nist.gov/publications/detail/fips/202/final"},{"category":"external","summary":"SARIF 2.1.0 specification (OASIS) — emitted natively by the new test_ndaal_binsec gate","url":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html"},{"category":"external","summary":"ndaal-binsec — ndaal fork of binsec emitting native validated SARIF 2.1.0 + Markdown","url":"https://crates.io/crates/ndaal-binsec"}],"title":"ndaal Information Advisory: ndaal_public_nvulnlookup 0.1.48 — CWE dashboard relocated under /attacks/ with 308 redirects, five-family hash sidecar contract enforced everywhere, new test_ndaal_binsec gate","tracking":{"current_release_date":"2026-05-26T00:00:00.000Z","generator":{"engine":{"name":"ndaal CSAF Generator","version":"1.0.0"}},"id":"ndaal-sa-2026-075","initial_release_date":"2026-05-26T00:00:00.000Z","revision_history":[{"date":"2026-05-26T00:00:00.000Z","number":"1.0.0","summary":"Initial informational advisory announcing ndaal_public_nvulnlookup 0.1.48.  Four user-visible items: (1) CWE dashboard relocated from /dashboards/cwe to /attacks/cwe under a new Attacks navbar dropdown; legacy paths serve HTTP 308 with id-revalidating handlers; /api/v1/cwe/* namespace unchanged.  (2) Five-family cryptographic-hash sidecar contract (sha-256 + sha-512 + sha3-512 + blake3-512 + shake256-512) enforced in create_release.sh and update_ansible_role.sh; new backfill_5sidecar_contract.{sh,bats} tool retroactively brings v0.1.31 → v0.1.48 + role files/ up to the contract (315 new blake3 + 315 new shake256 per-file sidecars + 34 new aggregate manifests committed).  (3) New test_ndaal_binsec quality gate emitting native validated SARIF 2.1.0 + Markdown from the ndaal-binsec fork.  (4) Five pre-existing structural bugs in verify_static_assets_{molecule,debian13}.sh cleared so both verify pipelines run end-to-end against a fresh Vagrant box and the six Molecule container distributions.  Plus the role files refresh to 0.1.48, the role-defaults version-bump 0.1.44 → 0.1.48, the update_ansible_cfg_project_specific.{sh,bats} canonical sweep, and two ancillary regression fixes (test_inline_script_escape, test_proptest).  Status: final."}],"status":"final","version":"1.0.0"}},"product_tree":{"branches":[{"category":"vendor","name":"ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG","branches":[{"category":"product_name","name":"nvulnlookup","branches":[{"category":"product_version_range","name":"vers:cargo/<0.1.48","product":{"name":"ndaal_public_nvulnlookup (vl-web / vl-cli / vl-core / vl-feeders / vl-models) before 0.1.48 — CWE dashboard at /dashboards/cwe; three-family hash sidecar contract only (sha-256 + sha-512 + sha3-512); five known structural bugs in verify_static_assets_{molecule,debian13}.sh blocking end-to-end Ansible-role verification.","product_id":"CSAFPID-0001"}},{"category":"product_version","name":"0.1.48","product":{"name":"ndaal_public_nvulnlookup 0.1.48 — CWE dashboard at /attacks/cwe with 308 redirects from /dashboards/cwe*; five-family hash sidecar contract (sha-256 + sha-512 + sha3-512 + blake3-512 + shake256-512) in create_release.sh, update_ansible_role.sh, and the new backfill_5sidecar_contract.sh tool; new test_ndaal_binsec gate (native validated SARIF 2.1.0 + Markdown); end-to-end verify_static_assets_{molecule,debian13}.sh pipelines.","product_id":"CSAFPID-0002"}}]}]}]}}