Renames the product name in every user-visible surface and internal
self-reference: page title, nav/shell, login/MFA pages, email templates and
subject prefixes ([VULNCHECK] → [TRUEVULN]), TOTP issuer label, report/PDF
headers, notification previews, outbound User-Agent/HTTP-Referer headers we
set ourselves, docs (README, ARCHITECTURE, PROJECT_OVERVIEW, DATABASE_SCHEMA,
README.DEV, TROUBLESHOOTING is untouched — see below), and .env.example
placeholder config (LDAP/OIDC/SAML example domains and paths).
Also renamed the on-disk cache file paths (/tmp/vulncheck-*.zip|csv|json →
/tmp/truevuln-*), kept consistent across the two files that share the
cvelistV5 ZIP cache path — first run after deploy re-downloads that ~557 MB
cache once (harmless, disposable).
Deliberately LEFT UNCHANGED (not branding — real external references or
infra identifiers; renaming the text without renaming the underlying thing
would just break/mislead):
- The actual Gitea repo URL/path (gitea.isuit.ch/vulncheck/vulncheck) and the
README lines derived from it (git clone target dir, tree listing) — a real
repo rename is a manual Gitea-side step (Settings → repository name) the
user would need to do themselves, and existing clones would need
`git remote set-url` after.
- The real support mailbox (support-vulncheck.sq9vd@passmail.net, in both
README and TROUBLESHOOTING) and the Buy Me A Coffee link — both point to
accounts that still exist under the old name; renaming the text alone
wouldn't create new ones.
- GitNexus MCP resource URIs in CLAUDE.md/AGENTS.md (gitnexus://repo/
vulncheck/...) — tied to GitNexus's own index name for this repo, not our
branding; those files are untracked in this repo anyway.
- docker-compose.yml container/network/Postgres user+db names
(vulnmanager-*) — explicit user decision: infra naming carries real
deploy/data risk on an already-running instance and isn't part of the
product-branding ask.
- The Tailwind color token class `vulncheck-blue` (frontend/app/globals.css)
— invisible internal CSS variable name, renaming it would touch ~270
className occurrences for zero user-visible benefit.
Verified: backend py_compile clean on every touched .py file; frontend tsc
clean (two pre-existing, unrelated errors remain: assets/page.tsx SVG title
prop, mfa-setup missing qrcode.react types). All diffs are exact-string
renames — no other changes riding along.
1. Samsung SMR precision (tester's point 1): security.samsungmobile.com's
yearly page (?year=YYYY) serves ALL ~12 months' content server-side in the
raw HTML — the accordion is pure CSS/JS, it doesn't gate what's delivered
— so it IS reliably parseable per month, contrary to what I assumed
earlier. New samsung_smr_service parses each SMR-MMM-YYYY block: Google
Critical/High CVEs MINUS the "Not applicable to Samsung devices" list,
plus Samsung Semiconductor Critical/High fixes. Cached per year (24h).
android_cve_service.check_android_cves now takes `manufacturer`: Samsung
devices try the SMR month first (source 'samsung-smr'), falling back to
raw ASB (source 'android-asb') only when SMR doesn't cover that month or
the fetch fails. Non-Samsung Android stays on ASB. This directly fixes
the false positive the tester hit: CVE-2025-59604 (Qualcomm-only) is
explicitly "Not applicable to Samsung devices" on Samsung's own page and
is now excluded — verified against the live page (absent from the parsed
June-2026 set).
2. Cache bug (tester's point 2): a device stuck showing only the newest
month's CVEs despite older months (verified live: 2025-09 had 59, 2025-12
had 57 AOSP critical/high CVEs) turned out to be stale cache entries from
before today's URL-format and SoC-section-filter fixes — the "non-empty is
immutable" cache rule kept serving pre-fix (empty or wrong) data forever.
Bumped _CACHE_PREFIX (asb_month_v2_) so every month is refetched under the
current, correct logic.
Both parsers verified against live data (JS + Python) before shipping:
19 months of Samsung SMR (2025-01–2026-07) parsed without error with
plausible per-month counts; ASB severity counts confirmed non-zero and
variable across all 12 lookback months.
Raw ASB import created false positives on Samsung (and any) devices: ASB
lists chipset-vendor CVEs (Qualcomm/MediaTek/Unisoc/Imagination/Arm) that
only affect devices with that SoC — Samsung's own SMR marks many "Not
applicable to Samsung devices". The parser now walks section headers + rows
in order and keeps only the AOSP sections (Framework/System/Kernel/Runtime/
Media/Google Play/Widevine) that apply to any Android device at that patch
level; SoC/vendor sections are dropped.
Verified on 2025-09: 115 total → 59 AOSP kept, ~49 SoC dropped; the Framework
KEV CVE-2025-48543 is retained.
(Samsung's own page can't scope per-device either without JS — it loads
month bodies via AJAX — so AOSP-section filtering is the robust fix. Samsung-
proprietary SVE CVEs remain out of scope.)
- android-asb: from 2026 Google nests the bulletin under a year segment
(/bulletin/2026/2026-01-01); older months stay flat (/bulletin/2025-10-01).
fetch_asb_month now tries the year-nested URL first, then flat. Verified:
2026-01 → nested 200/flat 404; 2025-xx → nested 404/flat 200.
- cvelistV5 scan: stop using lessThanOrEqual as fixed_version — that bound
means the version is still affected (no published fix), so leave
fixed_version empty (correct "no patch available", e.g. 7-Zip CVE-2026-58052
≤26.02). Only lessThan is a real fix target.
- app-cve OS scan: add macOS (cpe:2.3:o:apple:macos) alongside iOS/iPadOS so
Mac assets get OS CVEs (e.g. Apple CVE-2026-43700, previously only Defender
saw it).
Future ASB months Google hasn't published yet return 404. fetch_asb_month
only cached successful months, so every Android device re-fetched the same
404 months on every sync (the tester saw 2026-01…06 hammered dozens of times).
Now empty/404 results are cached too, with a 3-day TTL: months with CVEs stay
immutable/cached forever; empty months are skipped for 3 days, then retried
so a newly-published month is picked up. Legacy list-format cache entries
still read correctly.
(The 404s are expected — those months aren't published on source.android.com
yet; the 2025 months that exist already produced android-asb findings.)
For Intune-managed Android devices, raise real-CVE findings for the months
the device is behind on patches. Device patch level (androidSecurityPatchLevel,
e.g. 2025-03-01) → every monthly Android Security Bulletin published after it
lists CVEs the device hasn't received. Fetched from source.android.com
(stable, static, per-month) and parsed (CVE + severity, severity carried
across rowspan rows); cached per month in a Setting.
Source 'android-asb' (real CVE ids → EPSS/KEV/CVSS enrichment applies). Wired
into the Intune sync alongside the patch-level-staleness headline finding.
Why not Samsung's SMR page: securityUpdate.smsb ignores the year/month query
param and loads the month via JS — a plain fetch returns the same latest month
regardless (verified: 2025-03/-04/-09 all identical). ASB is the upstream
source for the Google CVEs Samsung ships (the security-critical bulk).
Samsung-proprietary SVE CVEs aren't covered (their page is unscrapeable).
Volume guards: Critical + High only, last 12 months (tunable via _MAX_MONTHS
/ _WANT_SEV). Verified month math + the ASB parser against the live bulletins
(2025-09 → 109 CVEs, per-month distinct).