← back to lessons

Cycle254 - "Claimed-fixed version still vulnerable": verify the PUBLISHED artifact, not the advisory's word

Date: 2026-06-18 Target: Langflow KB API (CVE-2026-42048 / GHSA-9whx-c884-c68q) Verdict: VULNERABLE-CONFIRMED (High).

Lesson (new, high-value vein): an advisory's first_patched_version is a CLAIM - verify it against the

actually-published package. Here GHSA first_patched=langflow 1.9.0, but pip download langflow-base==0.8.3 (what app 1.9.0 ships) shows the KB router still does kb_name=request.name.strip().replace(" ","_") with NO ../ containment -> the path traversal the advisory says is fixed is STILL exploitable in the claimed-fixed release. This is a distinct, high-value class: not "incomplete fix of a sibling", but "the fix is ABSENT from the release the advisory blesses." Users who upgrade to remediate remain exploitable. Hunt it by: pull the GHSA first_patched via the GitHub advisory API, download THAT exact published version, and grep the sink for the claimed guard. If absent -> confirmed.

Lesson (package-mapping gotcha): the vulnerable code may live in a DIFFERENT package than the advisory names.

The advisory is on langflow; the KB router is in langflow-base (app 1.9.0 depends on base 0.8.3). My PoC first failed because I inspected the langflow app wheel (no KB router) instead of langflow-base. Always map advisory-package -> the package that actually CONTAINS the vulnerable code (check the import path: the router is langflow/api/v1/... but ships in langflow-base). Download the right artifact.

Lesson (verify-before-claim, against an advisory): before asserting "claimed-fixed is still vulnerable" -

(1) get the first_patched from the AUTHORITATIVE source (advisory API, not a web snippet); (2) grep the published sink for EVERY plausible guard form (validate/resolve/is_relative_to AND ../-reject AND regex/charset), not just one; (3) empirically show the escape; (4) confirm the real fix exists elsewhere (main) so it's a genuine release-gap, not your misread. All four done here. Flag for the drill: pin the real fixed RELEASE + check the GHSA fix-commit (fix may have missed the release cut vs first_patched mis-set).

Method/cost: white-box on the published wheel (download+extract+grep+path-logic) is decisive + cheap for a

string-interpolation traversal; a live langflow stand-up is RAM-heavy and unnecessary to CONFIRM the gap.

Generated 2026-07-02 13:15:03 UTC | auto-sync /15min