This document outlines the secure logging practices that must be followed when adding log statements to the Rushomon codebase.
Sensitive information includes:
- Email addresses
- User IDs (sub, id fields)
- Personal names
- IP addresses
- Authentication tokens
- Session identifiers
- Any personally identifiable information (PII)
When logging is necessary for debugging, always hash sensitive information using SHA256:
use sha2::{Digest, Sha256};
// ✅ CORRECT: Hash sensitive information
let user_id_hash = {
let mut hasher = Sha256::new();
hasher.update(user.id.to_string().as_bytes());
format!("{:x}", hasher.finalize())
};
let email_hash = user.email.as_ref().map(|email| {
let mut hasher = Sha256::new();
hasher.update(email.as_bytes());
format!("{:x}", hasher.finalize())
});
println!(
"User action: id_hash={}, email_hash={:?}",
user_id_hash, email_hash
);// ❌ FORBIDDEN: Never log sensitive data directly
println!(
"User action: id={}, email={:?}",
user.id, user.email // This exposes sensitive information
);When adding log statements that might involve user data:
- Identify Sensitive Data: Review all variables being logged
- Hash When Necessary: Apply SHA256 hashing to any sensitive fields
- Use Generic Messages: When possible, log high-level events without specific data
- Code Review: All logging changes must be reviewed for security compliance
// ✅ Good: Hash user identifiers
println!(
"Auth attempt: user_hash={}, provider={}",
hash_user_id(&user_id), provider
);
// ❌ Bad: Expose user identifiers
println!("Auth attempt: user_id={}, provider={}", user_id, provider);// ✅ Good: Generic success/failure messages
println!("API request processed: status={}, endpoint={}", status, endpoint);
// ❌ Bad: Include user-specific data
println!("API request: user_email={}, status={}", email, status);// ✅ Good: Hash context identifiers
println!(
"Error in user context: context_hash={}, error_type={}",
hash_context(&context), error_type
);
// ❌ Bad: Include user context directly
println!("Error for user {}: {}", user.email, error);Create reusable hashing utilities:
pub fn hash_user_id(id: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(id.as_bytes());
format!("{:x}", hasher.finalize())
}
pub fn hash_email(email: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(email.as_bytes());
format!("{:x}", hasher.finalize())
}- Clippy Rules: Configured in
Cargo.tomlwith strict linting - Security Review: All PRs must pass security review for logging practices
- Code Review: Reviewers must check for sensitive data exposure
- Security Audit: Regular audits of logging statements
If you're unsure whether data is sensitive:
- Assume it's sensitive and hash it
- Ask for review before committing
- Use generic messages when possible
- User Privacy: Protects user information from logs
- Security: Reduces risk of data exposure
- Compliance: Helps meet privacy regulations (GDPR, CCPA)
- Debugging: Still provides useful debugging information without exposing data
Remember: Hash it, don't expose it! 🔐