Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions .github/.trivyignore
Original file line number Diff line number Diff line change
@@ -1,15 +1 @@
# =============================
# Accepted Risk Vulnerabilities
# =============================

# Accepting risk due to Python 3.8 support.
CVE-2025-50181 # Requires misconfiguration of urllib3, which agent does not do without intervention
CVE-2025-66418 # Malicious servers could cause high resource consumption
CVE-2025-66471 # Malicious servers could cause high resource consumption

# =======================
# Ignored Vulnerabilities
# =======================

# Not relevant, only affects Pyodide
CVE-2025-50182
# Empty for now
4 changes: 2 additions & 2 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Distributed under the following license(s):

## [urllib3](https://pypi.org/project/urllib3)

Copyright (c) 2008-2019 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
Copyright (c) 2008-2020 Andrey Petrov and contributors.

Distributed under the following license(s):

Expand All @@ -46,7 +46,7 @@ Distributed under the following license(s):

## [wrapt](https://pypi.org/project/wrapt)

Copyright (c) 2013-2019, Graham Dumpleton
Copyright (c) 2013-2025, Graham Dumpleton
All rights reserved.

Distributed under the following license(s):
Expand Down
4 changes: 1 addition & 3 deletions newrelic/common/agent_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,7 @@ def _connection(self):
return self._connection_attr

retries = urllib3.Retry(total=False, connect=None, read=None, redirect=0, status=None)
self._connection_attr = self.CONNECTION_CLS(
self._host, self._port, strict=True, retries=retries, **self._connection_kwargs
)
self._connection_attr = self.CONNECTION_CLS(self._host, self._port, retries=retries, **self._connection_kwargs)
return self._connection_attr

def close_connection(self):
Expand Down
14 changes: 12 additions & 2 deletions newrelic/packages/asgiref_compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@
import inspect


# Python 3.12 deprecates asyncio.iscoroutinefunction() as an alias for
# inspect.iscoroutinefunction(), whilst also removing the _is_coroutine marker.
# The latter is replaced with the inspect.markcoroutinefunction decorator.
# Until 3.12 is the minimum supported Python version, provide a shim.

if hasattr(inspect, "iscoroutinefunction"):
iscoroutinefunction = inspect.iscoroutinefunction
else:
iscoroutinefunction = asyncio.iscoroutinefunction # type: ignore[assignment]

def is_double_callable(application):
"""
Tests to see if an application is a legacy-style (double-callable) application.
Expand All @@ -46,10 +56,10 @@ def is_double_callable(application):
if hasattr(application, "__call__"):
# We only check to see if its __call__ is a coroutine function -
# if it's not, it still might be a coroutine function itself.
if asyncio.iscoroutinefunction(application.__call__):
if iscoroutinefunction(application.__call__):
return False
# Non-classes we just check directly
return not asyncio.iscoroutinefunction(application)
return not iscoroutinefunction(application)


def double_to_single_callable(application):
Expand Down
6 changes: 3 additions & 3 deletions newrelic/packages/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
# This file is used by dependabot to keep track of and recommend updates
# to the New Relic Python Agent's dependencies in newrelic/packages/.
opentelemetry_proto==1.32.1
urllib3==1.26.19
wrapt==2.0.0
asgiref==3.6.0 # We only vendor asgiref.compatibility.py
urllib3==2.6.2
wrapt==2.0.1
asgiref==3.11.0 # We only vendor asgiref.compatibility.py
2 changes: 1 addition & 1 deletion newrelic/packages/urllib3/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2008-2020 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
Copyright (c) 2008-2020 Andrey Petrov and contributors.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
155 changes: 132 additions & 23 deletions newrelic/packages/urllib3/__init__.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,57 @@
"""
Python HTTP library with thread-safe connection pooling, file post support, user friendly, and more
"""
from __future__ import absolute_import

from __future__ import annotations

# Set default logging handler to avoid "No handler found" warnings.
import logging
import sys
import typing
import warnings
from logging import NullHandler

from . import exceptions
from ._base_connection import _TYPE_BODY
from ._collections import HTTPHeaderDict
from ._version import __version__
from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url
from .filepost import encode_multipart_formdata
from .filepost import _TYPE_FIELDS, encode_multipart_formdata
from .poolmanager import PoolManager, ProxyManager, proxy_from_url
from .response import HTTPResponse
from .response import BaseHTTPResponse, HTTPResponse
from .util.request import make_headers
from .util.retry import Retry
from .util.timeout import Timeout
from .util.url import get_host

# === NOTE TO REPACKAGERS AND VENDORS ===
# Please delete this block, this logic is only
# for urllib3 being distributed via PyPI.
# See: https://github.com/urllib3/urllib3/issues/2680
# Ensure that Python is compiled with OpenSSL 1.1.1+
# If the 'ssl' module isn't available at all that's
# fine, we only care if the module is available.
try:
import urllib3_secure_extra # type: ignore # noqa: F401
import ssl
except ImportError:
pass
else:
warnings.warn(
"'urllib3[secure]' extra is deprecated and will be removed "
"in a future release of urllib3 2.x. Read more in this issue: "
"https://github.com/urllib3/urllib3/issues/2680",
category=DeprecationWarning,
stacklevel=2,
)
if not ssl.OPENSSL_VERSION.startswith("OpenSSL "): # Defensive:
warnings.warn(
"urllib3 v2 only supports OpenSSL 1.1.1+, currently "
f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. "
"See: https://github.com/urllib3/urllib3/issues/3020",
exceptions.NotOpenSSLWarning,
)
elif ssl.OPENSSL_VERSION_INFO < (1, 1, 1): # Defensive:
raise ImportError(
"urllib3 v2 only supports OpenSSL 1.1.1+, currently "
f"the 'ssl' module is compiled with {ssl.OPENSSL_VERSION!r}. "
"See: https://github.com/urllib3/urllib3/issues/2168"
)

__author__ = "Andrey Petrov ([email protected])"
__license__ = "MIT"
__version__ = __version__

__all__ = (
"HTTPConnectionPool",
"HTTPHeaderDict",
"HTTPSConnectionPool",
"PoolManager",
"ProxyManager",
Expand All @@ -52,15 +62,18 @@
"connection_from_url",
"disable_warnings",
"encode_multipart_formdata",
"get_host",
"make_headers",
"proxy_from_url",
"request",
"BaseHTTPResponse",
)

logging.getLogger(__name__).addHandler(NullHandler())


def add_stderr_logger(level=logging.DEBUG):
def add_stderr_logger(
level: int = logging.DEBUG,
) -> logging.StreamHandler[typing.TextIO]:
"""
Helper for quickly adding a StreamHandler to the logger. Useful for
debugging.
Expand All @@ -87,16 +100,112 @@ def add_stderr_logger(level=logging.DEBUG):
# mechanisms to silence them.
# SecurityWarning's always go off by default.
warnings.simplefilter("always", exceptions.SecurityWarning, append=True)
# SubjectAltNameWarning's should go off once per host
warnings.simplefilter("default", exceptions.SubjectAltNameWarning, append=True)
# InsecurePlatformWarning's don't vary between requests, so we keep it default.
warnings.simplefilter("default", exceptions.InsecurePlatformWarning, append=True)
# SNIMissingWarnings should go off only once.
warnings.simplefilter("default", exceptions.SNIMissingWarning, append=True)


def disable_warnings(category=exceptions.HTTPWarning):
def disable_warnings(category: type[Warning] = exceptions.HTTPWarning) -> None:
"""
Helper for quickly disabling all urllib3 warnings.
"""
warnings.simplefilter("ignore", category)


_DEFAULT_POOL = PoolManager()


def request(
method: str,
url: str,
*,
body: _TYPE_BODY | None = None,
fields: _TYPE_FIELDS | None = None,
headers: typing.Mapping[str, str] | None = None,
preload_content: bool | None = True,
decode_content: bool | None = True,
redirect: bool | None = True,
retries: Retry | bool | int | None = None,
timeout: Timeout | float | int | None = 3,
json: typing.Any | None = None,
) -> BaseHTTPResponse:
"""
A convenience, top-level request method. It uses a module-global ``PoolManager`` instance.
Therefore, its side effects could be shared across dependencies relying on it.
To avoid side effects create a new ``PoolManager`` instance and use it instead.
The method does not accept low-level ``**urlopen_kw`` keyword arguments.

:param method:
HTTP request method (such as GET, POST, PUT, etc.)

:param url:
The URL to perform the request on.

:param body:
Data to send in the request body, either :class:`str`, :class:`bytes`,
an iterable of :class:`str`/:class:`bytes`, or a file-like object.

:param fields:
Data to encode and send in the request body.

:param headers:
Dictionary of custom headers to send, such as User-Agent,
If-None-Match, etc.

:param bool preload_content:
If True, the response's body will be preloaded into memory.

:param bool decode_content:
If True, will attempt to decode the body based on the
'content-encoding' header.

:param redirect:
If True, automatically handle redirects (status codes 301, 302,
303, 307, 308). Each redirect counts as a retry. Disabling retries
will disable redirect, too.

:param retries:
Configure the number of retries to allow before raising a
:class:`~urllib3.exceptions.MaxRetryError` exception.

If ``None`` (default) will retry 3 times, see ``Retry.DEFAULT``. Pass a
:class:`~urllib3.util.retry.Retry` object for fine-grained control
over different types of retries.
Pass an integer number to retry connection errors that many times,
but no other types of errors. Pass zero to never retry.

If ``False``, then retries are disabled and any exception is raised
immediately. Also, instead of raising a MaxRetryError on redirects,
the redirect response will be returned.

:type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.

:param timeout:
If specified, overrides the default timeout for this one
request. It may be a float (in seconds) or an instance of
:class:`urllib3.util.Timeout`.

:param json:
Data to encode and send as JSON with UTF-encoded in the request body.
The ``"Content-Type"`` header will be set to ``"application/json"``
unless specified otherwise.
"""

return _DEFAULT_POOL.request(
method,
url,
body=body,
fields=fields,
headers=headers,
preload_content=preload_content,
decode_content=decode_content,
redirect=redirect,
retries=retries,
timeout=timeout,
json=json,
)


if sys.platform == "emscripten":
from .contrib.emscripten import inject_into_urllib3 # noqa: 401

inject_into_urllib3()
Loading
Loading