📋 What Is It?
Unsafe Consumption of APIs occurs when developers blindly trust data received from third-party APIs without proper validation and sanitization. Even if your own API is secure, consuming compromised or malicious third-party APIs can introduce vulnerabilities into your system.
API10
OWASP Rank
3rd Party
API Trust Issue
Supply Chain
Attack Vector
⚠️ Common Exploits
- Unvalidated Data: Trust external API responses without validation
- Injection Attacks: XSS, SQLi via third-party API responses
- Compromised APIs: Third-party API hacked, serves malicious data
- No Input Sanitization: External data stored/displayed without escaping
- Broken Integrations: Weak authentication to third-party services
- Data Leakage: Sending sensitive data to third-party APIs
🔴 Attack Flow
1. Your API calls third-party weather API
↓
2. Third-party API compromised by attacker
↓
3. Returns malicious payload with XSS
↓
4. Your API displays data without escaping
↓
5. BREACH: XSS executed on your users!
↓
2. Third-party API compromised by attacker
↓
3. Returns malicious payload with XSS
↓
4. Your API displays data without escaping
↓
5. BREACH: XSS executed on your users!
❌ Vulnerable Code
// Bad: Blindly trust third-party API response
@app.route('/api/weather')
def get_weather():
city = request.args.get('city')
# Call third-party weather API
response = requests.get(
f'https://weather-api.com/city/{city}'
)
# VULNERABLE: No validation of response!
weather_data = response.json()
# Directly store in database
Weather.create(
city=weather_data['city'], ← Could contain SQLi!
description=weather_data['description'] ← Could contain XSS!
)
return jsonify(weather_data)
// Bad: No SSL verification
response = requests.get(
'https://third-party-api.com/data',
verify=False ← DANGEROUS! Allows MITM attacks
)
// Bad: Sending sensitive data to third-party
@app.route('/api/analytics')
def track_event():
user = get_current_user()
# Sends sensitive data to analytics service
requests.post('https://analytics.com/track', json={
'user_id': user.id,
'email': user.email, ← PII leaked!
'ssn': user.ssn, ← Sensitive data leaked!
'credit_card': user.cc_last4 ← Financial data leaked!
})
// Bad: No timeout on third-party calls
response = requests.get(
'https://slow-api.com/data'
# No timeout - could hang forever!
)
✅ Secure Code
// Good: Validate and sanitize third-party data
from bleach import clean
import re
def validate_weather_response(data):
"""Validate structure and sanitize content"""
if not isinstance(data, dict):
raise ValueError("Invalid response format")
# Whitelist expected fields
required_fields = ['city', 'temperature', 'description']
for field in required_fields:
if field not in data:
raise ValueError(f"Missing field: {field}")
# Sanitize strings
data['city'] = clean(data['city'], tags=[], strip=True)
data['description'] = clean(data['description'], tags=[], strip=True)
# Validate data types and ranges
if not isinstance(data['temperature'], (int, float)):
raise ValueError("Invalid temperature type")
if not -100 <= data['temperature'] <= 150:
raise ValueError("Temperature out of range")
return data
@app.route('/api/weather')
def get_weather():
city = request.args.get('city')
try:
# Secure API call with timeout and SSL verification
response = requests.get(
f'https://weather-api.com/city/{city}',
timeout=5, # 5 second timeout
verify=True, # Verify SSL certificate
headers={
'Authorization': f'Bearer {API_KEY}'
}
)
response.raise_for_status() # Raise on HTTP errors
weather_data = response.json()
# Validate and sanitize response
validated_data = validate_weather_response(weather_data)
# Use parameterized queries (prevents SQLi)
Weather.create(
city=validated_data['city'],
temperature=validated_data['temperature'],
description=validated_data['description']
)
return jsonify(validated_data)
except requests.Timeout:
return {'error': 'Third-party API timeout'}, 504
except requests.RequestException as e:
logger.error(f"API error: {e}")
return {'error': 'External service unavailable'}, 503
except ValueError as e:
logger.warning(f"Invalid response: {e}")
return {'error': 'Invalid data from external API'}, 502
// Good: Minimal data sharing with third-parties
@app.route('/api/analytics')
def track_event():
user = get_current_user()
# Only send anonymous/aggregated data
requests.post('https://analytics.com/track',
json={
'user_id_hash': hash(user.id), # Hashed, not actual ID
'event': 'page_view',
'timestamp': datetime.utcnow().isoformat()
# NO PII, NO sensitive data!
},
timeout=3,
verify=True
)
// Good: Circuit breaker for third-party APIs
from pybreaker import CircuitBreaker
third_party_breaker = CircuitBreaker(
fail_max=5, # Open after 5 failures
timeout_duration=60 # Stay open for 60 seconds
)
@third_party_breaker
def call_third_party_api(url):
return requests.get(url, timeout=5, verify=True)
✓ Prevention Checklist
- Validate all third-party API responses
- Sanitize data before storing or displaying
- Always verify SSL/TLS certificates
- Set timeouts on external API calls
- Use schema validation for responses
- Implement circuit breakers for resilience
- Never trust external data implicitly
- Minimize data sent to third-parties
- Encrypt sensitive data in transit
- Monitor third-party API health
- Have fallback mechanisms
- Regular security audits of integrations
🔍 Detection & Tools
Validation Tools:
JSON Schema
Pydantic
Joi
Marshmallow
Bleach
DOMPurify
Monitoring Tools:
Datadog
New Relic
Prometheus
Sentry
PyBreaker
How to Test:
- Mock third-party APIs with malicious payloads
- Test with XSS/SQLi in response data
- Verify timeout handling
- Test SSL certificate validation
- Check error handling for invalid responses
- Monitor data sent to third-parties
🌍 Real-World Breaches
- SolarWinds (2020): Supply chain attack via compromised third-party software
- British Airways (2018): Third-party script injected malicious code
- Ticketmaster (2018): Compromised third-party chatbot stole payment data
- Target (2013): Breach via compromised HVAC vendor credentials
- Magecart Attacks: Compromised third-party JavaScript libraries stealing credit cards
📌 Quick Tips
- DO NOT trust third-party data without validation
- DO NOT disable SSL verification
- DO NOT send PII to third-parties unnecessarily
- DO validate response schemas
- DO sanitize all external data
- DO set timeouts on API calls
- DO implement circuit breakers
📜 Compliance
Related Standards:
- GDPR Art. 28 - Processor Requirements
- PCI-DSS Requirement 12.8 - Third-party Management
- SOC 2 CC9.2 - Vendor Management
- ISO 27001 A.15.1.1 - Supplier Relationships
- NIST 800-161 - Supply Chain Risk