Repository navigation
OpenHands recipe lock: PyJWT 2.14.0 relock closes ten advisories (unblocks the required osv-scanner check) - #525
Merged
Conversation
…p the PyJWT ignore and rebind the oauthlib allowance Nine PyJWT advisories published 2026-09-29 (one Critical, five High, three Medium) failed the required osv-scanner check on blueprints/runtime-workers/openhands/requirements.lock (CI run 36657687493). PyJWT 2.14.0 fixes them and GHSA-w6j9-cwv2-h6wq, which the 2026-09-29 ignore hid. - requirements.lock: three lines (pyjwt 2.13.0 -> 2.14.0 and its two hashes), made with the recipe's own method (uv 0.12.17, the pinned SDK archive, one `uv lock` with the four 09-27 upgrades plus pyjwt==2.14.0); a fresh single-command run is byte-identical. pins.json requirements_sha256 rebound. - The GHSA-w6j9-cwv2-h6wq ignore and IGNORE_SCOPES entry are deleted; the lock's IGNORE_ALLOWED_LOCKS entry keeps the two oauthlib advisories at the relocked sha256 and names the new record, which carries the 09-29 review forward. - oauthlib stays 3.3.1 (4.0.0 is inside the 7-day window until 2026-10-05T06:01Z). - Checks: the pinned osv-scanner 2.6.0 CI command over 49 lockfiles exits 0 with no PyJWT ignore; the previous lock under the same config exits 1 with ten advisories; the recipe's hashed install sequence and SDK import check pass in a scratch venv. Receipt, returned outputs, research and README notes and the decision addendum are included. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…protocol, last commit) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
…idence-reviewer, session 21's evidence-reviewer and stack-verifier) Neither review found a defect in the lock change; the findings were about the record. Fixed here: - 2.14.0 "fixes all ten" is now attributed to the OSV and GitHub ranges (all ten first patched 2.14.0, section H of the returned outputs); the changelog names nine, the tenth's fix sits under an id neither database serves. - oauthlib carry-forward: the PyJWT wheel (the installed artifact) and sdist are searched for oauthlib with the command shown and a positive control (requests-oauthlib's wheel: 80 hits); "one replaced artifact" corrected to two files of one release. - as-of time, one identical overturn list in the receipt, research.md and the decision, and the follow-up trigger for PyJWT 2.15.1 with oauthlib 4.0.0; the oauthlib relock now has an owner and a date (#518: due 2026-10-08). - oauthlib 4.0.0 pre-check: imports and requests-oauthlib 2.0.0's unit tests give identical results under 3.3.1 and 4.0.0. - limitations added: the grader venv (PyJWT 2.10.1), the reinstall requirement, the host-network import check, the unreconciled "Filtered 7" count; stale wording fixed (README, the decision's present-tense list, "every artifact"). - returned outputs rebuilt: no truncated lines, exit lines for uv lock and uv lock --check, '(derived)' labels, the push runs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…st commit) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s, owner name, PyJWT 2.15.0 decision point, honest output labels) All text and evidence-form; the lock, pins.json and the test file are unchanged. - #518 now says what this record claims (owner bc, session native-agent-stack-bc; exact window times; the 2.15.0 decision point; the relock command with oauthlib added and pyjwt 2.14.0 replaced by 2.15.1); its updatedAt is recorded in the receipt. - Every window statement carries an as-of time and the exit times (PyJWT 2.15.0 2026-09-30T16:56:01Z, oauthlib 4.0.0 2026-10-05T06:01:19Z, PyJWT 2.15.1 2026-10-05T18:40:43Z, 7 days after the later file upload on PyPI); the toml no longer speaks in the present tense. - 2.15.0's Security item (recursion errors from deeply nested payloads, the payload counterpart of GHSA-8wjv) gets a recorded reason for staying on 2.14.0 (no decode of attacker-controlled tokens found in the recipe venv) and a decision point when 2.15.0 leaves the window; one identical overturn list carries the triggers. - Returned outputs rebuilt so no line claims more than it is: each command as run, sections G, H and J with the real commands, the full pytest output (-rf --tb=line) for both oauthlib versions, the requests-oauthlib sdist hash (one of the lock's), the test dependency versions, '(derived)' and '(abridged)' labels; 'identical' reworded to 'the same outcome for each test' (the two failures are timing assertions that also fail under oauthlib 3.3.1). - README: grype's advisories are for the four 09-27 versions only; the receipt's evidence class names the run of unchanged upstream tests; 'cannot have failed' is 'most likely did not fail'. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…t commit) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
seathatflowsinourveins
deleted the
res-openhands-pyjwt-2140-20260930
branch
September 30, 2026 04:00
This was referenced Sep 30, 2026
seathatflowsinourveins
added a commit
that referenced
this pull request
Sep 30, 2026
…outputs (D2), honest output labels (#529) * PyJWT relock record: follow-up for the second review's residuals (redis decode search, timing range from the outputs, honest output labels) Text and evidence only; the lock, pins.json, tests and .github/osv-scanner.toml are unchanged (the toml text was already correct at #525). - D1: the reason for staying on PyJWT 2.14.0 until the joint relock now covers every PyJWT decode found in the relocked venv (section K of the returned outputs, a static search of 10,746 installed .py files with its script published): google-auth (oauth2/id_token.py:153, a module nothing outside google-auth imports), LiteLLM (proxy modules, not run), oauthlib (common.py:221, no caller outside oauthlib), redis 7.2.1 (auth/token.py:89, verify_signature false on a token its configured credential provider supplies; nothing outside redis references redis.auth.token or JWToken) and mcp (encode only); the recipe's own code imports neither redis nor jwt. - D2: the two failing requests-oauthlib tests' miss (assertAlmostEqual of an integer expiry against a float one) is computed from the retained outputs (0.09 to 0.39 s) and explained: it follows the fractional second of the run's clock, so they fail on almost any run under oauthlib 3.3.1 and 4.0.0 alike. - Nits: the returned outputs' header rule now names its exceptions ('(abridged)', '(derived)', '#', excerpts, the ~ substitution and the rounding of window times), section D shows its real command, section G shows each command as run, and the builder script and the section K script are published (evidence/relock-2026-09-30.builder.sh.txt, .jwt-callers.py.txt). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Register the follow-up's files in the evidence manifest (hot file, last commit) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * PyJWT relock follow-up, repair round for session 21's read (aliased imports, google-auth :146, LiteLLM :1516, honest checks) Text, script and evidence only; the lock, pins.json, tests and .github/osv-scanner.toml are unchanged. - N1: section K's script now follows every PyJWT import form (`import jwt`, `import jwt as X`, `from jwt import ...`), counts only names bound to the jwt module, and so cites google-auth's PyJWT decode at oauth2/id_token.py:146 (the :153 `jwt.decode` beside it is google-auth's own jwt module) and adds LiteLLM's `import jwt as _jwt` decode at mcp_management_endpoints.py:1516. The conclusion (no decode of an attacker-controlled token reachable in the recipe venv) is unchanged. - N3: the recipe is searched recursively (12 files, not 8), the google-auth outside-reference check excludes only google/auth and google/oauth2, litellm.proxy gets its own outside-reference check, and the "10,746 files" wording says what it leaves out (PyJWT's own files and installer tooling). Section K reproduces byte for byte from the published script. - N2: the 0.38-0.43 s figure is stated as a first run's terminal output that was not retained; the 0.22-0.28 s figure is the one in this file's git history (f77612b). - N4: the outputs header names every exception (abridged commands, derived lines, comments, excerpts, path placeholders), command lines show the real loops and paths, `osv-scanner --version` is its own command, and the script and builder names agree. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Re-register the follow-up's repaired files in the evidence manifest (hot file, last commit) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Scout <scout@local> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
osv-scannercheck (one pull_request log read; main push runs from 23:33Z on also concluded failure, logs not read), and the tenth (GHSA-w6j9-cwv2-h6wq) was ignored. OSV and GitHub list 2.14.0 as the first patched release for all ten. The change deletes that ignore and itsIGNORE_SCOPESentry and rebinds the lock'sIGNORE_ALLOWED_LOCKSentry (the two oauthlib advisories) to the relocked sha256, with a new receipt that carries the 2026-09-29 reachability review forward. oauthlib stays 3.3.1 (4.0.0 was published 2026-09-28T06:01Z, inside the 7-day window; its advisories stay ignored until 2026-10-13); its relock is tracked in Relock OpenHands onto oauthlib 4.0.0 / PyJWT 2.15.1 by 2026-10-08 (osv ignores from #517 expire 2026-10-13) #518 (owner bc, session native-agent-stack-bc; joint relock with PyJWT 2.15.1 earliest 2026-10-05T18:40:43Z, due 2026-10-08; a decision point at 2026-09-30T16:56:01Z, when PyJWT 2.15.0 leaves the window). Every window statement in the record is as of 2026-09-30T03:27:54Z.e45328d3(main).lane:foundation(registering the files inmanifests/evidence.jsonthrough the hot-file protocol does not make it shared).blueprints/runtime-workers/openhands/,.github/osv-scanner.toml,tests/test_osv_lockfile_coverage.py,docs/decisions/2026-09-22-github-automation-closure.md,evidence/receipts/,manifests/evidence.json(last commit).SOTA sources
2.14.0): released 2026-09-11, sdist sha25677283c83fb56ecf566a886c757a714bc83668e38156de2cce8263302f42e0b86, wheel sha256ad0cef71c756a56e74863c2919cf0985f72decbcfcb550ee2f422e7c62b5eedc(both equal the lock's hashes, read from the PyPI JSON API);CHANGELOG.rstv2.14.0 "Security" and "Fixed" sections, read from the sdist (it names nine of the ten advisories; the tenth's fix is listed under an id neither GitHub nor OSV serves).pins.jsonsource_archiveanduv_lock, both digests equal), astral-sh/uv@0.12.17docs/concepts/resolution.mdL142-L173 (environments, lockfile preferences), and this repository's 2026-09-27 relock inblueprints/runtime-workers/openhands/research.md(the same method with a fifth version-pinned upgrade)..github/workflows/security-scan.yml) and command.evidence/receipts/osv-oauthlib-pyjwt-reachability-20260929.jsonand itsdocs/decisions/2026-09-22-github-automation-closure.mdentry.Evidence-class table
pyjwtline and its two hashes); both PyJWT 2.14.0 hashes equal PyPI's and the release is not yankedsource_review(structural comparison and registry read; not an execution)evidence/relock-2026-09-30.txtsections C and Duv.lockandrequirements.lock, byte for byte;uv lock,uv lock --checkanduv exportexit 0,cmpexits 0local_integration(documented method, uv 0.12.17)locks[0].method; section Clocal_integration(local runs of the pinned scanner, not CI; this PR's ownosv-scannercheck is the CI run)osv_scanner.runs; section Euv pip checkpasses and the SDK import check passeslocal_integration(host scratch venv; no model request; not the image; not an OpenHands run)locks[0].install_check; section Flocal_integration(search with a positive control) plussource_review(unchanged inputs)carried_forward_review; section Gimport requests_oauthlib, google_auth_oauthlib.flowworks and requests-oauthlib 2.0.0's own unit tests give 72 passed and the same 2 failed (timing assertions that also fail under 3.3.1)oauthlib_4_0_0_precheck; section J (full pytest output)Local commands run
The full
unittestdiscovery runs in CI'svalidatecheck.Decision record
docs/decisions/2026-09-22-github-automation-closure.md, dated addendum 2026-09-30 (alternatives: PyJWT 2.15.1 or 2.15.0, relocking oauthlib 4.0.0 now, extending the ignores to the nine; overturn: an advisory only a later PyJWT release fixes, an OpenHands run that fails with 2.14.0, a recorded reason for staying on 2.14.0 that no longer holds when PyJWT 2.15.0 leaves the window (2026-09-30T16:56:01Z), oauthlib 4.0.0 or PyJWT 2.15.1 clearing their windows on 2026-10-05; the follow-up relock has an owner and a due date of 2026-10-08 in #518).Host evidence
This PR adds a receipt under
evidence/receipts/, notevidence/hosts/.scripts/validate.py(exit 0 above) validates the receipt and its registration.platform_statuschange.Residuals
uv.lock, which still pins PyJWT 2.13.0, and the grader venv (OpenHands/benchmarks@405bae7'suv.lock, synced byinstall-grader.sh) pins PyJWT 2.10.1; neither is in the OSV inventory, and the 2026-09-28 grype record of the image predates these advisories. The relock covers the recipe venv only.host.pyrefuses to run it otherwise); this host has none.Checklist
🤖 Generated with Claude Code