Back to Cheat Sheets

🔒 Model Theft

OWASP LLM Top 10 - LLM10

MEDIUM RISK

📋 What Is It?

Model Theft (also known as Model Extraction or Model Stealing) occurs when attackers gain unauthorized access to proprietary LLM models, their weights, architectures, or training data through various extraction techniques. This vulnerability is critical because it can lead to intellectual property loss, competitive disadvantage, and exposure of sensitive training data embedded in the model.

LLM10 OWASP Rank
High IP Impact
Medium Likelihood

⚠️ Common Exploits

  • API Extraction: Query-based model cloning through APIs
  • Model File Theft: Unauthorized access to model weights/checkpoints
  • Side-Channel Attacks: Extracting info via timing, memory patterns
  • Infrastructure Compromise: Breaching storage/training systems
  • Insider Threats: Employees stealing proprietary models

🔴 Attack Flow

1. Attacker identifies valuable LLM model

2. Sends thousands of API queries to extract behavior

3. Trains surrogate model on collected responses

4. Achieves similar performance to original model

5. BREACH: Proprietary model stolen/replicated!

❌ Vulnerable Code

# Bad: Unrestricted API access @app.route('/api/predict', methods=['POST']) def predict(): # VULNERABLE: No rate limiting! input_data = request.json['input'] # Returns full model output prediction = model.predict(input_data) # VULNERABLE: Exposes confidence scores and probabilities return { 'prediction': prediction, 'confidence': model.confidence, 'all_probabilities': model.all_class_probs # Too much info! } # Bad: Model files accessible # Model stored in public S3 bucket model_url = "https://s3.amazonaws.com/public-bucket/model.pkl" # PUBLIC! # Bad: No authentication @app.route('/model/download') def download_model(): # VULNERABLE: Anyone can download! return send_file('proprietary_model.h5')

✅ Secure Code

# Good: Protected API with rate limiting and monitoring from flask_limiter import Limiter from flask_limiter.util import get_remote_address limiter = Limiter( app, key_func=get_remote_address, default_limits=["100 per day", "10 per hour"] ) @app.route('/api/predict', methods=['POST']) @limiter.limit("5 per minute") @require_api_key def secure_predict(): # Validate API key and user api_key = request.headers.get('X-API-Key') user = validate_api_key(api_key) if not user: return {'error': 'Invalid API key'}, 401 input_data = request.json['input'] # Log query for anomaly detection log_query(user.id, input_data, timestamp=datetime.now()) # Detect extraction attempts if detect_model_extraction(user.id, input_data): alert_security_team(user.id, "Possible model theft attempt") return {'error': 'Suspicious activity detected'}, 429 # Get prediction prediction = model.predict(input_data) # Return minimal information return { 'prediction': prediction.top_class, # Only top result # No confidence scores or probabilities } # Good: Secure model storage class SecureModelStorage: def __init__(self): # Encrypt model at rest self.encryption_key = load_encryption_key() self.model_path = '/secure/encrypted/models/' def save_model(self, model): # Encrypt model before saving encrypted_model = encrypt( serialize(model), self.encryption_key ) # Save to secure location with restricted access secure_path = os.path.join(self.model_path, 'model.enc') with open(secure_path, 'wb') as f: f.write(encrypted_model) # Set strict permissions (owner read-only) os.chmod(secure_path, 0o400) # Log access audit_log("Model saved", user=current_user) def load_model(self): # Require authentication if not check_authorized(): raise PermissionError("Unauthorized model access") # Load and decrypt with open(self.model_path, 'rb') as f: encrypted_model = f.read() model = deserialize( decrypt(encrypted_model, self.encryption_key) ) audit_log("Model loaded", user=current_user) return model # Good: Extraction detection class ExtractionDetector: def __init__(self): self.user_queries = {} self.threshold = 100 # queries per hour def detect_extraction_attempt(self, user_id, query): # Track query patterns now = datetime.now() if user_id not in self.user_queries: self.user_queries[user_id] = [] self.user_queries[user_id].append({ 'timestamp': now, 'query': hash(str(query)) }) # Check for suspicious patterns recent_queries = [ q for q in self.user_queries[user_id] if (now - q['timestamp']).seconds < 3600 ] # Too many queries in short time if len(recent_queries) > self.threshold: return True # Check for systematic querying if self.is_systematic(recent_queries): return True return False def is_systematic(self, queries): # Detect automated/scripted access patterns if len(queries) < 10: return False # Check for consistent timing (bot-like behavior) intervals = [ (queries[i+1]['timestamp'] - queries[i]['timestamp']).seconds for i in range(len(queries) - 1) ] # Very consistent intervals = likely automated avg_interval = sum(intervals) / len(intervals) variance = sum((i - avg_interval) ** 2 for i in intervals) / len(intervals) return variance < 2.0 # Low variance = suspicious

✓ Prevention Checklist

  • Implement strict rate limiting on APIs
  • Require authentication for all model access
  • Encrypt models at rest and in transit
  • Monitor for extraction attempts
  • Limit information in API responses
  • Use watermarking for model outputs
  • Implement access logging and auditing
  • Restrict model file access with permissions
  • Use secure infrastructure for training/deployment
  • Have legal protections (NDAs, IP agreements)

🔍 Detection & Tools

Protection Tools:

API Gateway Rate Limiters Model Watermarking Tools Encryption Libraries Access Control (IAM) SIEM Solutions

Monitoring Tools:

Anomaly Detection Usage Analytics Cloud Access Security Brokers DLP (Data Loss Prevention)

How to Test:

  • Test rate limiting effectiveness
  • Verify model file access controls
  • Check API response information leakage
  • Audit access logs regularly
  • Test extraction detection mechanisms

🌍 Real-World Examples

  • OpenAI Model Cloning (Research): Researchers cloned GPT models using API queries and distillation
  • Google vs Uber (2017): Engineer accused of stealing self-driving car AI trade secrets
  • Model Weight Leaks: Proprietary model checkpoints accidentally exposed on GitHub
  • API Scraping: Competitors reverse-engineered models through systematic API querying
  • Insider Theft: Employees leaked proprietary training datasets and model architectures

📌 Quick Tips

  • DO NOT expose model files publicly
  • DO NOT skip rate limiting
  • DO NOT return excessive API information
  • DO encrypt models at rest
  • DO monitor for extraction
  • DO use watermarking

📜 Compliance

Related Standards:

  • ISO 27001 A.8.2.3 (Information Asset Handling)
  • Trade Secret Law - DTSA, UTSA
  • NIST 800-53 MP-2, SC-28
  • CWE-522 Insufficiently Protected Credentials
  • SOC 2 CC6.6, CC6.7