Skip to content

The requests>=2.32.2 floor admits the .netrc credential leak (CVE-2024-47081); the default IP-pinned path neutralises it, but the webhook allow_private_destinations path sends ano… (CR-A16-081) #528

Open

Description

@cemililik

Wave 2 · theme D2-7: Next-release technology updates · highest severity Low · 2 finding(s) · effort trivial

Summary

pyproject.toml:62 sets requests>=2.32.2. datasets 4.7.0 imposes the same floor (Requires-Dist requests>=2.32.2), and the K-3 lower venv installs 2.32.2. requests before 2.32.4 picks the .netrc entry by netloc.split(':')[0] (get_netrc_auth in 2.32.2). A URL such as https://victim.example:@​attacker.example/ therefore gets victim.example's credentials while connecting to attacker.example. In forgelm/_http.py the default path (allow_private=False) resolves the host, rebuilds the URL with a public IP literal and drops the userinfo (_http.py:302-327, 563-578). The pinned Session then looks .netrc up by the IP, so no foreign credential is attached. When allow_private=True, safe_post and safe_get call module-level requests.post / requests.request with the raw URL (_http.py:583-597, 722-730), whose Session has trust_env on, and the leak happens. The only caller that passes allow_private=True is the webhook notifier (webhook.py:154,167), driven by WebhookConfig.allow_private_destinations (config.py:1488-1491, default False). judge.py:248, synthetic.py:240 and _doctor.py:500,541 always use the pinned path. The URL is operator config or url_env (TC-T; TC-U only in the CI-PR case of IN-01), an…

Primary finding

CR-A16-081 — The requests>=2.32.2 floor admits the .netrc credential leak (CVE-2024-47081); the default IP-pinned path neutralises it, but the webhook allow_private_destinations path sends another host's .netrc c…

severity Low · reachability documented-opt-in · intent intended-but-harmful · confidence likely · independently confirmed · reproduced end to end

What happens. pyproject.toml:62 sets requests>=2.32.2. datasets 4.7.0 imposes the same floor (Requires-Dist requests>=2.32.2), and the K-3 lower venv installs 2.32.2. requests before 2.32.4 picks the .netrc entry by netloc.split(':')[0] (get_netrc_auth in 2.32.2). A URL such as https://victim.example:@​attacker.example/ therefore gets victim.example's credentials while connecting to attacker.example. In forgelm/_http.py the default path (allow_private=False) resolves the host, rebuilds the URL with a public IP literal and drops the userinfo (_http.py:302-327, 563-578). The pinned Session then looks .netrc up by the IP, so no foreign credential is attached. When allow_private=True, safe_post and safe_get call module-level requests.post / requests.request with the raw URL (_http.py:583-597, 722-730), whose Session has trust_env on, and the leak happens. The only caller that passes allow_private=True is the webhook notifier (webhook.py:154,167), driven by WebhookConfig.allow_private_destinations (config.py:1488-1491, default False). judge.py:248, synthetic.py:240 and _doctor.py:500,541 always use the pinned path. The URL is operator config or url_env (TC-T; TC-U only in the CI-PR case of IN-01), and the path needs a documented opt-in. So this is a footgun or hardening gap, not a vulnerability. The second floor advisory, CVE-2026-25645 (extract_zipped_paths, fixed 2.33.0), needs a local attacker, and the advisory itself says standard usage is not affected. requests 2.33.0 requires Python >=3.10, the same as ForgeLM, so raising the floor costs nothing.

Where.

Evidence.

  • Lower venv requests 2.32.2, NETRC set to a file with 'machine victim.example login svc password NETRC-SECRET'. For url https://victim.example:@​attacker.example/hook: safe_post allow_private=False sent to https://93.184.215.14/hook with no Authorization header; safe_post and safe_get with allow_private=True sent to the raw URL with Authorization 'Basic c3ZjOk5FVFJDLVNFQ1JFVA==' (svc:NETRC-SECRET). Latest venv requests 2.34.2: get_netrc_auth(raw url) returned None, and the header carried only the…

Recommended fix. Raise the floor to requests>=2.33.0, which clears both advisories. Optionally route the allow_private branch through a Session too and strip userinfo there. Setting trust_env=False would also drop env proxies, so prefer raising the floor.

Other findings with the same root cause

These close with the same fix; update them in the same pull request.

TECH-T12-008 — Supply-chain tooling, network dependencies and vulnerability scanning: requests>=2.32.2,<3.0.0 (core dependency floor) (range-unsound)

severity Next release

Item. requests>=2.32.2,<3.0.0 (core dependency floor) · verdict: range-unsound · urgency: Next release

State in ForgeLM. pyproject.toml:62 requests>=2.32.2,<3.0.0; the K-3 lower venv resolves 2.32.2; forgelm/_http.py is the SSRF-guarded HTTP chokepoint; the orphan requirements.txt:11 says requests>=2.31.0.

State of the ecosystem on 2026-10-01. Latest is 2.34.2 (2026-05-14), with no advisories. 2.32.2 is affected by PYSEC-2026-1872 / GHSA-9hjg-9r4m-mvj7 / CVE-2024-47081 (.netrc credentials can leak for crafted URLs; fixed 2.32.4) and PYSEC-2026-2275 / GHSA-gc5v-m9x4-r6x2 / CVE-2026-25645 (fixed 2.33.0); 2.31.0 additionally has CVE-2024-35195 (fixed 2.32.0).

Impact. A minimum-version install of the HTTP chokepoint (webhook, judge, teacher) carries a known credential-leak bug; exploitation needs a .netrc plus a crafted URL (IN-01 config: TC-T, TC-U in CI-PR). The lower-bound CI venv actually tests the vulnerable version.

Recommendation. Raise the floor to requests>=2.33.0 (no Python cost: both need >= 3.10); delete or regenerate requirements.txt.

Sources.

Acceptance criteria

  • A regression test reproduces the failure scenario and asserts the corrected behaviour.
  • Documentation listed above is corrected in English and in its Turkish mirror in the same PR.
  • Every finding in this issue is resolved or explicitly closed with a reason.

Found by the October 2026 ForgeLM code and documentation review against commit cab2947. Code links point at that commit; line numbers may have moved since. Finding IDs (CR-…, DOC-…, TECH-…) are stable references for this backlog.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: packaging-ciCode area: packaging-cibugSomething isn't workingdependenciesDependency or ecosystem currencysecuritySecurity-relevantseverity: lowMinor defect, inaccuracy or rough edgesource: review-2026-10Found by the October 2026 code and documentation reviewurgency: next-releaseTechnology currency: fix in the next releasewave: 2Roadmap wave 2: high severity, larger effort; next-release tech

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions