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
Metadata
| Tracking ID | ndaal-sa-2026-075 |
|---|---|
| Category | csaf_informational_advisory |
| CSAF Version | 2.1 |
| Status | final |
| Version | 1.0.0 |
| Publisher | ndaal Gesellschaft fuer Sicherheit in der Informationstechnik mbH & Co KG |
| TLP | CLEAR |
| Initial Release | 2026-05-26T00:00:00.000Z |
| Current Release | 2026-05-26T00:00:00.000Z |
Vulnerabilities (0)
No vulnerabilities.
Raw JSON
{
"$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"
}
}
]
}
]
}
]
}
}