Keras model-load deserialization = SATURATED (huntr); disclosure-gate kills it (cycle269, 2026-06-21)
Banked from cycle269 Phase-0 (huntr AI cash lane, Keras Native $4000). Disclosure-gate-FIRST WALK. The methodology refinements are the value.
Verdict: Keras model-load deser is SATURATED + actively-contested
- safe_mode/
__lambda__/func_load RCE (the prime model-load-RCE angle): the CVE-2025-9905 sibling-fix is COMPLETE at HEAD 3.15.0. All 3 func_load sinks (serialization_lib.py:689, lambda_layer.py:202/221) guarded by in_safe_mode()-or-default-True (PR #23048 merged, PR #21602 merged). The one unfixed vector (raw-native-callable nested in config, invoked later via from_config) is ALREADY PUBLIC: issue #22705 + OPEN PR #22736 = $0 dup, do not pursue.
- StringLookup/IndexLookup/TextVectorization vocab file/SSRF (CVE-2025-12058): fixed in 3.11.4, structurally complete in 3.15.0 (shared chokepoint IndexLookup.set_vocabulary in_safe_mode guard covers all siblings) = $0 dup.
- DECISIVE saturation signal: issue #23055 (OPEN) "Validate Huntr security reports before OSS sunset" = the maintainers are actively triaging a BACKLOG of huntr reports on this exact deserialization surface. -> 3+ disclosure strikes + active third-party mining = SATURATED. WALK.
Methodology invariants banked
- Issue-tracker saturation detection (cheap, run in the disclosure gate): search the repo's OPEN issues/PRs for meta-signals like "Validate Huntr reports", "security backlog", "before sunset", a cluster of recent security PRs (#23048/#21602/#23115 here). A repo actively triaging a huntr/security backlog on YOUR target surface = SATURATED = other researchers are already there. This is the fastest saturation kill - do it BEFORE any source analysis.
- Scope-overrides-param invariant (keras safe_mode):
in_safe_mode() (global SafeModeScope) OVERRIDES the safe_mode param. A sibling-fix audit must check BOTH the param thread AND scope establishment; a path is safe if EITHER a SafeModeScope is active OR the param default holds. (Residual fragility worth a maintainer hardening note, NOT a vuln: the legacy-h5 compile path + trainer.compile_from_config run with NO SafeModeScope backstop, relying solely on each {optimizers,losses,metrics}.deserialize keeping safe_mode=True as the lib default - a future refactor could silently open it. Wrap in SafeModeScope. Hardening, not RCE.)
- Shared-chokepoint completeness: when a base class (IndexLookup) centralizes the risky op and all siblings forward to it, ONE guard covers the family. To find a real sibling you must locate a class that does NOT route through the guarded method. If all roads lead to the chokepoint, the sibling hunt is dead.
- Disclosure-gate version-diff primacy: a "load-time I/O via config path" or "deser RCE" candidate MUST be version-diffed against the CVE's FIX release first (12058 fixed in 3.11.4; auditing 3.15.0 = a patched tree). LIVE-path existence (the dangerous arg still appears in get_config/docstrings) is NOT evidence of vuln - the runtime guard is what matters. Source presence != exploitability.
- Model-File-Formats huntr campaign = inherently high-saturation: the whole $4000 "Model File Formats" category (Keras/ONNX/Joblib/SafeTensors/GGUF/TensorRT/TF-SavedModel) is a FAMOUS, actively-mined huntr campaign -> EVERY format's obvious deser/parser/traversal angle is being hunted. Pick by FRESHEST-unpatched-cluster (a recent CVE cluster = narrow-patching = sibling probability) NOT by fame, and run the issue-tracker saturation check first. Related: [[feedback_cross_fork_portlag_primitive]], the disclosure-gate-is-gate0 doctrine, SATURATION-IS-POPULARITY-DRIVEN.