Exposure of Sensitive Information to an Unauthorized Actor
The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
There are many different kinds of mistakes that introduce information exposures. The severity of the error can range widely, depending on the context in which the product operates, the type of sensitive information that is revealed, and the benefits it may provide to an attacker.
Cómo corregir esta vulnerabilidad
Estrategias de prevención para Information Exposure basadas en 14 reglas de detección de Shoulder.
Use environment variables for configuration only; never log or return their values
package main import ( "log" "os" ) func main() { apiKey := os.Getenv("API_KEY") - log.Printf("API Key: %s", apiKey) + if apiKey == "" { + log.Fatal("API_KEY not configured") + } + log.Println("API key configured:", len(apiKey) > 0) + // Use apiKey internally, never log or return it }
Store API keys in environment variables, never log them, and protect model endpoints with authentication
- client := openai.NewClient("sk-proj-1234567890abcdefghijklmnop") - log.Printf("Using key: %s", apiKey) - http.Handle("/models/", http.FileServer(http.Dir("./models"))) + client := openai.NewClient(os.Getenv("OPENAI_API_KEY")) + log.Printf("Request completed: model=%s tokens=%d", model, usage.TotalTokens) + + modelsHandler := http.FileServer(http.Dir("./models")) + http.Handle("/models/", authMiddleware(rateLimiter(modelsHandler)))
Mask PII and redact credentials before sending data to LLM APIs, and use structured logging
- resp, _ := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{ - Messages: []openai.ChatCompletionMessage{{ - Content: fmt.Sprintf("User SSN: %s, Password: %s", user.SSN, password), - }}, - }) - log.Printf("Request: %v", messages) + safeMessage := maskPII(userInput) + safeMessage = redactCredentials(safeMessage) + + resp, _ := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{ + Messages: []openai.ChatCompletionMessage{{Content: safeMessage}}, + }) + log.Printf("Completed: model=%s tokens=%d", model, resp.Usage.TotalTokens)
Use secrets internally without exposing them in logs, responses, or client-side code
- app.get('/config', (req, res) => { - res.json({ apiKey: process.env.API_KEY }); - }); + const apiKey = process.env.API_KEY; + // Use the key server-side only + const result = await externalApi.call({ key: apiKey }); + res.json({ data: result });
Load API keys from environment variables and proxy LLM calls through your server
const openai = new OpenAI({ - apiKey: 'sk-proj-1234567890abcdefghijklmnop' + apiKey: process.env.OPENAI_API_KEY });
Mask or redact PII and credentials before sending data to LLM APIs
- const response = await openai.chat.completions.create({ - messages: [{ role: 'user', content: `Process: ${userRecord}` }] + const masked = maskPII(userRecord); + const response = await openai.chat.completions.create({ + messages: [{ role: 'user', content: `Process: ${masked}` }] });
Return generic error messages to users; log detailed errors server-side only
- from flask import jsonify - - @app.route('/api/data') - def handler(): - try: - return jsonify(process()) - except Exception as e: - return jsonify({'error': str(e), 'trace': traceback.format_exc()}), 500 + import logging + from flask import jsonify + + logger = logging.getLogger(__name__) + + @app.route('/api/data') + def handler(): + try: + return jsonify(process()) + except Exception as e: + logger.error(f"Error: {e}", exc_info=True) + return jsonify({'error': 'Internal server error'}), 500
Use Presidio or similar libraries to anonymize PII before sending data to LLM APIs
- messages = [{ - 'role': 'user', - 'content': f"User SSN: {user.ssn}, email: {user.email}. Summarize profile." - }] - logging.info(f"Request: {messages}") - response = openai.chat.completions.create(model='gpt-4', messages=messages) + from presidio_analyzer import AnalyzerEngine + from presidio_anonymizer import AnonymizerEngine + + analyzer = AnalyzerEngine() + anonymizer = AnonymizerEngine() + + def anonymize_text(text: str) -> str: + results = analyzer.analyze(text=text, language='en') + return anonymizer.anonymize(text=text, analyzer_results=results).text + + safe_message = anonymize_text(user_message) + messages = [{'role': 'user', 'content': safe_message}] + response = openai.chat.completions.create(model='gpt-4', messages=messages) + logger.info('Completed', extra={'model': 'gpt-4', 'tokens': response.usage.total_tokens})
Use explicit field selection or serializer schemas to exclude sensitive fields from responses
from flask import jsonify from models import User @app.route('/api/users') def get_users(): users = User.query.all() - return jsonify([u.__dict__ for u in users]) + return jsonify([{ + 'id': u.id, + 'email': u.email, + 'name': u.name + } for u in users])
Encuentra vulnerabilidades en tu código
Usa Shoulder para escanear tu código en busca de patrones Exposure of Sensitive Information to an Unauthorized Actor. 14 reglas.
# Scan with Shoulder CLI npx @shoulderdev/cli trust --cwe=200 # Or scan entire project npx @shoulderdev/cli trust .
Reglas de Detección (14)
Qué buscar en las revisiones de código
Estos patrones indican vulnerabilidades potenciales de Exposure of Sensitive Information to an Unauthorized Actor. Búscalos durante las revisiones de código y auditorías de seguridad.
Escanea tu base de código para Exposure of Sensitive Information to an Unauthorized Actor
Shoulder CLI encuentra patrones vulnerables en toda tu base de código.