# Risk map — psf/requests

> Canonical page: https://codevetter.com/unpack/requests/risk-map

# Risk map — psf/requests

Scanned commit 611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60 (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

As a library in ~4M dependent repos, the blast radius of any change here is close to maximal, and the highest-risk surfaces are the ones that decide whether credentials cross a trust boundary: `should_strip_auth`, `rebuild_proxies`, `prepare_url`, and `cert_verify`. Several behaviours are knowingly non-ideal and preserved for backwards compatibility — the http→https auth-retention carve-out, `_basic_auth_str` accepting non-strings, and `LookupDict.__getitem__` silently returning `None`. Environment trust is on by default (`trust_env=True`), so `.netrc`, `$NETRC`, `REQUESTS_CA_BUNDLE`/`CURL_CA_BUNDLE` and `*_proxy` variables all influence behaviour implicitly. Filesystem and process-global side effects exist in `extract_zipped_paths`, `atomic_open`, `set_environ`, and the import-time `pyopenssl.inject_into_urllib3()`.
- `should_strip_auth` intentionally keeps the `Authorization` header across an http:80 → https:443 redirect on the same host; the comment states this is not RFC 7235 behaviour and is retained only for backwards compatibility. — [src/requests/sessions.py#L154-L184](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/sessions.py#L154-L184)
- `rebuild_proxies` reconstructs `Proxy-Authorization` from proxy URL credentials but skips it when the target scheme starts with `https`, explicitly to avoid leaking the header into a TLS tunnel — a subtle invariant easy to break in a refactor. — [src/requests/sessions.py#L334-L368](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/sessions.py#L334-L368)
- Any URL containing a colon whose scheme does not start with `http` bypasses all URL preparation and is assigned verbatim to `self.url`, so `mailto:`/`data:`-style inputs skip IDNA, requoting and host validation entirely. — [src/requests/models.py#L503-L509](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/models.py#L503-L509)
- `verify=False` disables certificate and hostname validation at the urllib3 level (`cert_reqs = 'CERT_NONE'`, ca_certs cleared); the Session docstring is explicit that this exposes callers to MitM and is for testing only. — [src/requests/adapters.py#L307-L345](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/adapters.py#L307-L345) [src/requests/sessions.py#L466-L478](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/sessions.py#L466-L478)
- `trust_env=True` by default means an attacker-controlled or accidentally-set `REQUESTS_CA_BUNDLE`/`CURL_CA_BUNDLE` silently replaces the trust store for every request on the session. — [src/requests/sessions.py#L487-L490](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/sessions.py#L487-L490) [src/requests/sessions.py#L852-L860](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/sessions.py#L852-L860)
- `get_netrc_auth` reads credentials from a path taken from the `$NETRC` environment variable without restriction, and swallows `NetrcParseError`/`OSError` unless `raise_errors=True` — failures to read credentials are silent by default. — [src/requests/utils.py#L231-L280](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/utils.py#L231-L280)
- `extract_zipped_paths` performs file IO outside the repo root: it walks a path upward looking for a zip archive, then extracts a member into a `tempfile.mkstemp()` file that is never cleaned up, returning that path to the caller. — [src/requests/utils.py#L290-L326](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/utils.py#L290-L326)
- `_basic_auth_str` still accepts non-string usernames/passwords, coercing them with a `DeprecationWarning` promising removal in 3.0.0; the source comment preserves it precisely because callers depend on it. — [src/requests/auth.py#L34-L76](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/auth.py#L34-L76)
- Digest auth uses MD5 by default when the server omits an `algorithm` directive; MD5/SHA-1 usage is flagged `usedforsecurity=False` to appease FIPS builds but the weak-hash negotiation is server-driven. — [src/requests/auth.py#L166-L186](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/auth.py#L166-L186)
- `handle_401` re-sends the authenticated request directly through `r.connection.send(prep, **kwargs)`, bypassing `Session.send` — so session-level cookie extraction, hooks, and redirect resolution do not run for that hop. — [src/requests/auth.py#L300-L317](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/auth.py#L300-L317) [src/requests/sessions.py#L752-L791](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/sessions.py#L752-L791)
- `prepare_auth` blanket-applies `self.__dict__.update(r.__dict__)` from a user-supplied callable, meaning a third-party auth class can overwrite any attribute of the PreparedRequest including `url` and `hooks`. — [src/requests/models.py#L684-L697](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/models.py#L684-L697)
- `LookupDict.__getitem__` deliberately falls through to `None` for unknown keys, so a typo'd `requests.codes['okey']` silently yields `None` instead of raising — a footgun with no test-enforced guard. — [src/requests/structures.py#L118-L122](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/structures.py#L118-L122)
- `HTTPAdapter.get_connection` is live deprecated code retained for subclass compatibility; it emits a `DeprecationWarning` and, unlike `get_connection_with_tls_context`, does not incorporate verify/cert into the pool key. — [src/requests/adapters.py#L512-L554](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/adapters.py#L512-L554) [src/requests/adapters.py#L455-L511](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/adapters.py#L455-L511)
- `compat.py` is largely legacy: it still exports `is_py2`, `is_py3`, `basestring`, `numeric_types` and `integer_types` for a Python 2 that the project no longer supports (`requires-python = ">=3.10"`), and shadows the builtin `str`/`bytes` names. — [src/requests/compat.py#L51-L115](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/compat.py#L51-L115) [pyproject.toml#L16](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/pyproject.toml#L16)
- `packages.py` mutates the global `sys.modules` table at import time to alias urllib3/idna/chardet under `requests.packages.*` — a process-wide side effect purely for pre-2.16 backwards compatibility. — [src/requests/packages.py](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/src/requests/packages.py)
- `.coveragerc` omits `requests/packages/*`, a path that no longer exists since the move to `src/` layout, so the omit rule is dead configuration. (inferred) — [.coveragerc](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/.coveragerc) [pyproject.toml#L95-L96](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/pyproject.toml#L95-L96)
- Release-critical files are protected by CODEOWNERS requiring lead-maintainer review: `.github/workflows/`, `src/requests/__version__.py`, `HISTORY.md` and `pyproject.toml`. — [.github/CODEOWNERS](https://github.com/psf/requests/blob/611c6162cbc4ac2020a2f91c7cfa4f3abf9bbb60/.github/CODEOWNERS)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
