---
title: Không log thông tin nhạy cảm (token, password, PII)
impact: HIGH
impactDescription: Log trong iOS có thể đọc được qua Console.app, thiết bị bị jailbreak, hoặc crash logs gửi lên server. Credentials trong log đồng nghĩa với data breach.
tags: swift, ios, logging, security, credentials, privacy, pii
---

## Không log thông tin nhạy cảm (token, password, PII)

`NSLog`, `print()`, và `os_log` đều có thể bị capture bởi tool như Console.app hoặc bởi attacker khi thiết bị bị jailbreak. Không bao giờ log: password, access token, refresh token, thẻ tín dụng, số CMND/CCCD, hay thông tin cá nhân nhạy cảm.

**Incorrect (log thông tin nhạy cảm):**

```swift
func login(email: String, password: String) async {
    print("Attempting login with email: \(email), password: \(password)")  // !! password trong log

    do {
        let response = try await authService.login(email: email, password: password)
        // !! Token trong log
        NSLog("Login success. accessToken: %@, refreshToken: %@", response.accessToken, response.refreshToken)

        UserDefaults.standard.set(response.accessToken, forKey: "access_token")
    } catch {
        // !! Email trong log
        logger.error("Login failed for email: \(email), error: \(error)")
    }
}

func processPayment(cardNumber: String, cvv: String) {
    logger.info("Processing card: \(cardNumber), CVV: \(cvv)")  // !! PCI DSS violation
}
```

**Correct (log không chứa thông tin nhạy cảm):**

```swift
import OSLog

private let logger = Logger(subsystem: "com.app.auth", category: "Authentication")

func login(email: String, password: String) async {
    // Log action không log credentials
    logger.info("Login attempt initiated")

    do {
        let response = try await authService.login(email: email, password: password)
        // Chỉ log metadata - không log token value
        logger.info("Login succeeded. userId=\(response.userId, privacy: .public), tokenExpiry=\(response.expiresIn)")

        // Lưu token vào Keychain, không log
        try tokenManager.saveAccessToken(response.accessToken)
    } catch {
        // Log loại lỗi, không log email
        logger.warning("Login failed: \(error.localizedDescription, privacy: .public)")
    }
}

func processPayment(cardNumber: String, cvv: String) {
    // Chỉ log metadata về payment, không log card data
    let maskedCard = String(cardNumber.suffix(4))
    logger.info("Processing payment for card ending in \(maskedCard, privacy: .public)")
}
```

**Tools:** Code Review, `os.Logger` privacy API, MobSF static analysis

