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
36 changes: 32 additions & 4 deletions tavily/async_tavily.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,34 @@ def __init__(self, api_key: Optional[str] = None,
)
self._company_info_tags = company_info_tags

def _raise_for_status_secure(self, response):
"""
Secure version of response.raise_for_status() that prevents API key exposure.

This method sanitizes the error message to remove sensitive information like
API keys from Authorization headers before raising the exception.

Security Note: This prevents API key exposure in logs, error tracking systems,
and debug output when HTTP errors occur.
"""
if response.status_code >= 400:
# Create a sanitized error message without exposing sensitive headers
error_msg = f"{response.status_code} {response.reason_phrase} for url: {response.url}"

# Create the appropriate exception type based on status code
if response.status_code == 400:
raise httpx.HTTPStatusError(error_msg, request=response.request, response=response)
elif response.status_code == 401:
raise httpx.HTTPStatusError(error_msg, request=response.request, response=response)
elif response.status_code == 403:
raise httpx.HTTPStatusError(error_msg, request=response.request, response=response)
elif response.status_code == 404:
raise httpx.HTTPStatusError(error_msg, request=response.request, response=response)
elif response.status_code >= 500:
raise httpx.HTTPStatusError(error_msg, request=response.request, response=response)
else:
raise httpx.HTTPStatusError(error_msg, request=response.request, response=response)

async def _search(
self,
query: str,
Expand Down Expand Up @@ -116,7 +144,7 @@ async def _search(
elif response.status_code == 400:
raise BadRequestError(detail)
else:
raise response.raise_for_status()
self._raise_for_status_secure(response)

async def search(self,
query: str,
Expand Down Expand Up @@ -211,7 +239,7 @@ async def _extract(
elif response.status_code == 400:
raise BadRequestError(detail)
else:
raise response.raise_for_status()
self._raise_for_status_secure(response)

async def extract(self,
urls: Union[List[str], str], # Accept a list of URLs or a single URL
Expand Down Expand Up @@ -310,7 +338,7 @@ async def _crawl(self,
elif response.status_code == 400:
raise BadRequestError(detail)
else:
raise response.raise_for_status()
self._raise_for_status_secure(response)

async def crawl(self,
url: str,
Expand Down Expand Up @@ -419,7 +447,7 @@ async def _map(self,
elif response.status_code == 400:
raise BadRequestError(detail)
else:
raise response.raise_for_status()
self._raise_for_status_secure(response)

async def map(self,
url: str,
Expand Down
36 changes: 32 additions & 4 deletions tavily/tavily.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,34 @@ def __init__(self, api_key: Optional[str] = None, proxies: Optional[dict[str, st
"X-Client-Source": "tavily-python"
}

def _raise_for_status_secure(self, response):
"""
Secure version of response.raise_for_status() that prevents API key exposure.

This method sanitizes the error message to remove sensitive information like
API keys from Authorization headers before raising the exception.

Security Note: This prevents API key exposure in logs, error tracking systems,
and debug output when HTTP errors occur.
"""
if response.status_code >= 400:
# Create a sanitized error message without exposing sensitive headers
error_msg = f"{response.status_code} {response.reason} for url: {response.url}"

# Create the appropriate exception type based on status code
if response.status_code == 400:
raise requests.exceptions.HTTPError(error_msg, response=response)
elif response.status_code == 401:
raise requests.exceptions.HTTPError(error_msg, response=response)
elif response.status_code == 403:
raise requests.exceptions.HTTPError(error_msg, response=response)
elif response.status_code == 404:
raise requests.exceptions.HTTPError(error_msg, response=response)
elif response.status_code >= 500:
raise requests.exceptions.HTTPError(error_msg, response=response)
else:
raise requests.exceptions.HTTPError(error_msg, response=response)

def _search(self,
query: str,
search_depth: Literal["basic", "advanced"] = None,
Expand Down Expand Up @@ -102,7 +130,7 @@ def _search(self,
raise BadRequestError(detail)

else:
raise response.raise_for_status()
self._raise_for_status_secure(response)


def search(self,
Expand Down Expand Up @@ -195,7 +223,7 @@ def _extract(self,
elif response.status_code == 400:
raise BadRequestError(detail)
else:
raise response.raise_for_status()
self._raise_for_status_secure(response)

def extract(self,
urls: Union[List[str], str], # Accept a list of URLs or a single URL
Expand Down Expand Up @@ -293,7 +321,7 @@ def _crawl(self,
elif response.status_code == 400:
raise BadRequestError(detail)
else:
raise response.raise_for_status()
self._raise_for_status_secure(response)

def crawl(self,
url: str,
Expand Down Expand Up @@ -402,7 +430,7 @@ def _map(self,
elif response.status_code == 400:
raise BadRequestError(detail)
else:
raise response.raise_for_status()
self._raise_for_status_secure(response)

def map(self,
url: str,
Expand Down