Skip to content

requests dependency is pinned to a CVE-2024-47081 affected version (netrc user-info leak) #144

@hamizan-azman

Description

@hamizan-azman

Summary

The requests == 2.32.3 pin in pyproject.toml is affected by CVE-2024-47081 / GHSA-9hjg-9r4m-mvj7 (netrc credential leak through URL user-info parsing). The fix shipped in requests 2.32.4. Code paths in hackingBuddyGPT that send HTTP requests to attacker-influenced hosts can leak the operator's netrc credentials for the wrong machine to the wrong host.

Affected component

pyproject.toml at HEAD (d0ff901) line 31:

'requests == 2.32.3',

Anywhere hackingBuddyGPT performs an HTTP request whose URL is influenced by an attacker is exposed. The most direct path is src/hackingBuddyGPT/capabilities/http_request.py, where HTTPRequest._client = requests.Session() and cap("METHOD", path) calls self._client.request(method, self.host + path, ...). If self.host ever resolves to a value containing user-info (e.g. an attacker-supplied target URL of the form http://victim:x@attacker/...), the session triggers the vulnerable netrc lookup inside requests.

Root cause

In the affected requests versions, requests.utils.get_netrc_auth(url) parses the URL with urlparse(url).netloc.split(":")[0], returning the user-info username instead of the actual hostname when the URL contains user-info. The wrong machine's netrc entry is then attached to the request as HTTP Basic Auth and shipped to the real destination. The exact line in requests/utils.py of the version pinned in this repo:

host = ri.netloc.split(splitstr)[0]

The fix in requests 2.32.4 switches the netrc-host derivation to urlparse(url).hostname, which strips user-info before the lookup.

Reproduction

Tested against ipa-lab/hackingBuddyGPT at HEAD d0ff901 with the upstream's documented setup (pip install -e . resolves requests == 2.32.3).

  1. Plant a canary netrc entry for a host called attacker:
cat > ~/.netrc <<'EOF'
machine attacker
login leakvictim
password netrc-leaked-secret-CANARY
EOF
chmod 600 ~/.netrc
  1. Start a local TCP listener on 127.0.0.1:9999 that records the first incoming request.

  2. Drive a request from the hackingBuddyGPT HTTPRequest capability with an attacker user-info host. A minimal driver:

from hackingBuddyGPT.capabilities.http_request import HTTPRequest

cap = HTTPRequest(host="http://attacker:x@127.0.0.1:9999")
cap("GET", "/canary")

Observed at the listener under requests == 2.32.3:

GET /canary HTTP/1.1
Host: 127.0.0.1:9999
User-Agent: python-requests/2.32.3
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Authorization: Basic bGVha3ZpY3RpbTpuZXRyYy1sZWFrZWQtc2VjcmV0LUNBTkFSWQ==

bGVha3ZpY3RpbTpuZXRyYy1sZWFrZWQtc2VjcmV0LUNBTkFSWQ== is base64 of leakvictim:netrc-leaked-secret-CANARY. The credentials for machine attacker were attached to a request destined for 127.0.0.1. That is the vulnerability.

Control under requests == 2.32.4 (same driver, same canary, only the requests pin changed):

Authorization: Basic YXR0YWNrZXI6eA==

YXR0YWNrZXI6eA== decodes to attacker:x, which is the URL user-info passed through normally (standard RFC 3986 Basic-Auth conveyance, not a netrc leak). The patched netrc lookup correctly resolves 127.0.0.1 as the host, finds no matching entry, and attaches no canary credentials. The fix in 2.32.4 holds.

Expected behaviour

requests should derive the netrc-lookup host from the URL's actual destination, not from the user-info segment. That is what requests 2.32.4 does.

Suggested fix

Bump the pin in pyproject.toml:

-    'requests == 2.32.3',
+    'requests >= 2.32.4',

Or pin to the latest patch line, currently 2.34.x. Either way, the lower bound must be >= 2.32.4. >= 2.32.0 (and any of 2.32.0, 2.32.1, 2.32.2, 2.32.3) does not contain the fix and would leave hackingBuddyGPT exposed.

Severity

CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N (6.5 medium) is a reasonable baseline. The leak matters for hackingBuddyGPT because the agent follows URLs that can be influenced by output from the target system or from the LLM provider, and netrc credentials on an operator's box may include credentials for unrelated production systems.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions