fix(rust): Remove sensitive information from logs and docs
Security improvements: - Remove all debug logs that output tokens, keys, or credentials - Remove email addresses from debug output - Remove encrypted keys and nonces from logs - Remove specific account references from documentation - Add security guidelines to CLAUDE.md No sensitive information (PII, credentials, tokens) should be logged even in debug mode. Updated guidelines to prevent future occurrences. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -107,6 +107,15 @@ cargo fmt --check
|
||||
- Never commit to main branch
|
||||
- All CI checks must pass - the above commands simulate CI locally
|
||||
|
||||
### Security Guidelines
|
||||
**NEVER commit sensitive information:**
|
||||
- No real email addresses, usernames, or account IDs in code or documentation
|
||||
- No authentication tokens, API keys, or passwords (even for test accounts)
|
||||
- No debug logs that output credentials, keys, or personal information
|
||||
- Use generic examples like "user@example.com" in documentation
|
||||
- Remove all `log::debug!` statements that print sensitive data before committing
|
||||
- Avoid logging encrypted keys, nonces, or tokens even in encrypted form
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- `ENTE_CLI_CONFIG_DIR`: Override default config directory
|
||||
|
||||
@@ -111,7 +111,7 @@ The Rust CLI now has a **fully functional export capability** with proper file d
|
||||
## Testing Status 🧪
|
||||
|
||||
### Successfully Tested ✅
|
||||
- ✅ Export with real account (m@ente.io)
|
||||
- ✅ Export with real account
|
||||
- ✅ Small file decryption (JPEG images)
|
||||
- ✅ Large file decryption (33MB RAW file)
|
||||
- ✅ Metadata extraction for filenames
|
||||
|
||||
@@ -82,12 +82,9 @@ impl<'a> AuthClient<'a> {
|
||||
srp_attrs.mem_limit as u32,
|
||||
srp_attrs.ops_limit as u32,
|
||||
)?;
|
||||
log::debug!("KEK (hex): {}", hex::encode(&key_enc_key));
|
||||
|
||||
// Step 3: Derive login key
|
||||
let login_key = derive_login_key(&key_enc_key)?;
|
||||
log::debug!("loginSubKey (base64): {}", STANDARD.encode(&login_key));
|
||||
log::debug!("loginSubKey (hex): {}", hex::encode(&login_key));
|
||||
|
||||
// Step 4: Initialize SRP client
|
||||
let srp_salt = STANDARD.decode(&srp_attrs.srp_salt)?;
|
||||
|
||||
@@ -83,7 +83,7 @@ impl ApiClient {
|
||||
// Add auth token if account_id is provided
|
||||
if let Some(id) = account_id {
|
||||
if let Some(token) = self.get_token(id) {
|
||||
log::debug!("Adding auth token for account {id}: {token}");
|
||||
log::debug!("Adding auth token for account {id}");
|
||||
req = req.header(TOKEN_HEADER, token);
|
||||
} else {
|
||||
log::warn!("No token found for account {id}");
|
||||
|
||||
@@ -238,29 +238,21 @@ async fn add_account(
|
||||
|
||||
// Decrypt token if encrypted
|
||||
let token = if let Some(encrypted_token) = &auth_response.encrypted_token {
|
||||
log::info!("Encrypted token from server (base64): {encrypted_token}");
|
||||
log::info!("Public key (base64): {}", key_attributes.public_key);
|
||||
|
||||
let encrypted_bytes = decode_base64(encrypted_token)?;
|
||||
log::info!("Encrypted token bytes length: {}", encrypted_bytes.len());
|
||||
log::debug!("Encrypted token bytes length: {}", encrypted_bytes.len());
|
||||
|
||||
let decrypted = sealed_box_open(&encrypted_bytes, &public_key, &secret_key)?;
|
||||
log::info!("Decrypted token bytes length: {}", decrypted.len());
|
||||
log::info!("Decrypted token hex: {}", hex::encode(&decrypted));
|
||||
log::debug!("Decrypted token bytes length: {}", decrypted.len());
|
||||
|
||||
// Try to interpret as UTF-8 string first
|
||||
match String::from_utf8(decrypted.clone()) {
|
||||
Ok(token_str) => {
|
||||
log::info!("Decrypted token is UTF-8 string: {token_str}");
|
||||
log::debug!("Decrypted token is valid UTF-8");
|
||||
// If it's a string, use it as bytes
|
||||
token_str.into_bytes()
|
||||
}
|
||||
Err(_) => {
|
||||
log::info!("Token is not UTF-8, using raw bytes");
|
||||
log::info!(
|
||||
"Token as base64 URL: {}",
|
||||
base64::engine::general_purpose::URL_SAFE.encode(&decrypted)
|
||||
);
|
||||
log::debug!("Token is not UTF-8, using raw bytes");
|
||||
// If not UTF-8, use raw bytes
|
||||
decrypted
|
||||
}
|
||||
|
||||
@@ -23,16 +23,9 @@ pub async fn run_export(account_email: Option<String>) -> Result<()> {
|
||||
// Export specific account - try to find it with any app
|
||||
let all_accounts = storage.accounts().list()?;
|
||||
log::debug!("Found {} total accounts", all_accounts.len());
|
||||
for acc in &all_accounts {
|
||||
log::debug!("Account: email='{}', id={}", acc.email, acc.id);
|
||||
}
|
||||
let matching: Vec<Account> = all_accounts
|
||||
.into_iter()
|
||||
.filter(|a| {
|
||||
let matches = a.email == email;
|
||||
log::debug!("Comparing '{}' == '{}': {}", a.email, email, matches);
|
||||
matches
|
||||
})
|
||||
.filter(|a| a.email == email)
|
||||
.collect();
|
||||
|
||||
if matching.is_empty() {
|
||||
@@ -169,8 +162,6 @@ async fn export_account(storage: &Storage, account: &Account) -> Result<()> {
|
||||
Ok(key) => key,
|
||||
Err(e) => {
|
||||
log::error!("Failed to decrypt key for file {}: {}", file.id, e);
|
||||
log::debug!("encrypted_key: {}", &file.encrypted_key);
|
||||
log::debug!("key_decryption_nonce: {}", &file.key_decryption_nonce);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user