---
title: Không log thông tin nhạy cảm trong production build
impact: HIGH
impactDescription: print() và NSLog() trong iOS production build có thể bị đọc bởi device console (nếu device chưa enable device pairing protection) hoặc lộ trong crash report. Data nhạy cảm không được log ở bất kỳ level nào.
tags: swift, ios, logging, debug, print, nslog, sensitive-data, security
---

## Không log thông tin nhạy cảm trong production build

`print()` và `NSLog()` trong iOS production build vẫn in ra Console.app khi device được kết nối. Không log token, password, PII (tên, email, phone, địa chỉ), response body của API authentication, hoặc private key. Dùng conditional compilation `#if DEBUG` để chỉ log trong debug.

**Incorrect (log sensitive data):**

```swift
import Foundation

class AuthService {
    // !! Log access token - đọc được qua Console.app
    func handleLoginResponse(data: Data) {
        if let json = try? JSONDecoder().decode(LoginResponse.self, from: data) {
            print("Login success. Token: \(json.accessToken)")  // !! Token trong log!
            NSLog("User logged in: %@, token: %@", json.username, json.accessToken)  // !!
        }
    }
}

class PaymentService {
    // !! Log card number trong error
    func processPayment(cardNumber: String, amount: Decimal) {
        print("Processing payment for card: \(cardNumber), amount: \(amount)")  // Card number!
        guard amount > 0 else {
            NSLog("Invalid amount for card: %@", cardNumber)  // !! PCI violation
            return
        }
    }
}

class NetworkLogger: URLProtocol {
    // !! Log toàn bộ request/response body
    override func startLoading() {
        if let body = request.httpBody {
            print("Request body: \(String(data: body, encoding: .utf8) ?? "")") // Có thể chứa password!
        }
    }
}
```

**Correct (conditional logging, mask sensitive data):**

```swift
import Foundation
import OSLog

// SAFE: Dùng OSLog với privacy levels (iOS 14+)  
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "app", category: "Auth")

class AuthService {
    func handleLoginResponse(data: Data) {
        if let json = try? JSONDecoder().decode(LoginResponse.self, from: data) {
            // Log với private để tự động mask trong production
            logger.info("Login success for user: \(json.userId, privacy: .public)")
            // Token KHÔNG được log ở bất kỳ level nào
        }
    }
}

// SAFE: Wrapper log chỉ bật trong DEBUG
struct AppLogger {
    static func debug(_ message: String, file: String = #file, line: Int = #line) {
        #if DEBUG
        let filename = URL(fileURLWithPath: file).lastPathComponent
        print("[\(filename):\(line)] \(message)")
        #endif
    }

    static func info(_ message: @autoclosure () -> String) {
        #if DEBUG
        print("[INFO] \(message())")
        #endif
        // Trong production: dùng logging service như Crashlytics, DataDog
    }

    static func error(_ error: Error, context: [String: String] = [:]) {
        // Log error nhưng mask sensitive fields
        var safeContext = context
        // Xóa các key nhạy cảm
        ["token", "password", "card", "ssn", "email"].forEach { safeContext.removeValue(forKey: $0) }
        logger.error("Error: \(error.localizedDescription, privacy: .public), context: \(safeContext)")
    }
}

class PaymentService {
    func processPayment(cardToken: String, amount: Decimal) {
        // Log với masked card (chỉ 4 số cuối), không log full number
        let maskedToken = String(cardToken.prefix(8)) + "..."
        AppLogger.debug("Processing payment, token: \(maskedToken), amount: \(amount)")
    }
}

// SAFE: Network logger mask sensitive headers
class SafeNetworkLogger {
    private let sensitiveHeaders = ["Authorization", "Cookie", "X-API-Key"]

    func logRequest(_ request: URLRequest) {
        #if DEBUG
        var headers = request.allHTTPHeaderFields ?? [:]
        sensitiveHeaders.forEach { key in
            if headers[key] != nil { headers[key] = "[REDACTED]" }
        }
        AppLogger.debug("Request: \(request.url?.absoluteString ?? "") headers: \(headers)")
        #endif
    }
}
```

**Tools:** OSLog privacy levels (iOS 14+), Crashlytics, OWASP MASVS-STORAGE-2, Console.app (verify logs)
