General Pasteboard Access

ID

swift.general_pasteboard_access

Severity

high

Resource

Information Leak

Language

Swift

Tags

CWE:200, MASWE:0001, NIST.SP.800-53, OWASP:2021:A01

Description

The system-wide general pasteboard (UIPasteboard.general) in iOS is accessible to all applications without requiring explicit user permission. This creates a significant privacy and security vulnerability where sensitive information copied by users can be accessed by any app, including malicious or compromised applications running in the background.

The pasteboard (clipboard) is commonly used by users to copy and paste sensitive information such as:

  • Passwords and authentication credentials

  • Two-factor authentication (2FA) codes

  • Credit card numbers and financial information

  • API keys and access tokens

  • Personal messages and confidential data

  • Health information and social security numbers

When applications access UIPasteboard.general, they gain unrestricted read access to whatever the user has most recently copied. In iOS versions prior to 14, this access was completely silent with no user notification. Even in iOS 14 and later, while a notification banner appears when apps read the clipboard, no permission is required, and background apps can still monitor clipboard changes.

Rationale

The following example demonstrates vulnerable code that accesses the general pasteboard:

import UIKit

class PasteboardManager {
    // VULNERABLE: Accessing general pasteboard exposes data to all apps
    func pasteText_vulnerable1() -> String? {
        let pasteboard = UIPasteboard.general  // FLAW
        return pasteboard.string
    }

    // VULNERABLE: Reading clipboard content without user awareness
    func checkClipboard_vulnerable2() {
        if let clipboardText = UIPasteboard.general.string {  // FLAW
            print("Clipboard contains: \(clipboardText)")
            // This could be logging/exfiltrating user's sensitive data
        }
    }

    // VULNERABLE: Copying sensitive data to general pasteboard
    func copyPassword_vulnerable3(password: String) {
        UIPasteboard.general.string = password  // FLAW
        // Password is now accessible to all apps
    }

    // VULNERABLE: Monitoring clipboard for changes
    func monitorClipboard_vulnerable4() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(pasteboardChanged),
            name: UIPasteboard.changedNotification,
            object: UIPasteboard.general  // FLAW
        )
    }

    @objc func pasteboardChanged() {
        // Background app can silently monitor all clipboard changes
        if let text = UIPasteboard.general.string {  // FLAW
            // Potential data exfiltration
            sendToServer(text)
        }
    }

    private func sendToServer(_ data: String) {
        // Send data to external server
    }
}

// VULNERABLE: Auto-paste feature reading clipboard
class AutoPasteViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // VULNERABLE: Automatically reading clipboard when view appears
        if let clipboardURL = UIPasteboard.general.url {  // FLAW
            // Opening URLs from clipboard without user confirmation
            openURL(clipboardURL)
        }
    }

    private func openURL(_ url: URL) {
        UIApplication.shared.open(url)
    }
}

This code has several critical security problems:

  1. Silent data access: pasteText_vulnerable1() reads clipboard content without any indication to the user that their copied data is being accessed.

  2. Passive monitoring: checkClipboard_vulnerable2() demonstrates how apps can read whatever users have copied, potentially exposing passwords, 2FA codes, or personal information.

  3. Sensitive data exposure: copyPassword_vulnerable3() places a password in the general pasteboard, making it accessible to all apps on the device, not just the current app.

  4. Background surveillance: monitorClipboard_vulnerable4() shows how apps can register for clipboard change notifications and continuously monitor everything users copy, even when the app is in the background.

  5. Automatic exploitation: AutoPasteViewController demonstrates auto-paste attacks where apps automatically read and act on clipboard content when becoming active.

Attack Scenarios

Scenario 1: Password Exfiltration

A malicious app monitors the clipboard in the background:

// Malicious app code running in background
class MaliciousClipboardMonitor {
    init() {
        // Register for clipboard changes
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(stealClipboardData),
            name: UIPasteboard.changedNotification,
            object: UIPasteboard.general
        )
    }

    @objc func stealClipboardData() {
        // User copies password from password manager
        if let password = UIPasteboard.general.string {
            // Silently exfiltrate to attacker's server
            sendToAttackerServer(password)
        }
    }
}

Result: User’s passwords, 2FA codes, credit cards copied from other apps are stolen.

Scenario 2: 2FA Code Interception

User receives SMS with 2FA code "123456", copies it to paste into banking app. Malicious app running in background reads the code:

// Attacker's app
if let code = UIPasteboard.general.string {
    if code.count == 6 && code.allSatisfy({ $0.isNumber }) {
        // Detected 2FA code, exfiltrate immediately
        exfiltrate2FACode(code)
    }
}

Scenario 3: Cross-App Data Leakage

User copies API key from email to paste into legitimate app. A compromised app from the App Store reads it:

// Compromised app's telemetry code
func collectDiagnostics() {
    var diagnostics = ["version": appVersion]

    // "Accidentally" include clipboard content in diagnostics
    if let clipboard = UIPasteboard.general.string {
        diagnostics["clipboard"] = clipboard  // API keys, passwords leaked
    }

    sendTelemetry(diagnostics)  // Sent to analytics server
}

Remediation

Recommended Approach: Use Named Pasteboards

Instead of the general pasteboard, create app-specific named pasteboards that are private to your app:

import UIKit

class SecurePasteboardManager {
    // SECURE: Create app-specific, non-persistent pasteboard
    private static let privatePasteboard = UIPasteboard.withName(
        UIPasteboard.Name("com.example.app.private"),
        create: true
    )!

    static func setupPasteboard() {
        // Make pasteboard non-persistent (cleared when app terminates)
        privatePasteboard.isPersistent = false
    }

    // SECURE: Copy to private pasteboard only
    func copyText_secure1(_ text: String) {
        Self.privatePasteboard.string = text
        print("Text copied to private pasteboard (not accessible to other apps)")
    }

    // SECURE: Read from private pasteboard
    func pasteText_secure2() -> String? {
        return Self.privatePasteboard.string
    }

    // SECURE: Clear pasteboard after use
    func clearPasteboard_secure3() {
        Self.privatePasteboard.items = []
    }
}

// SECURE: Avoid clipboard for sensitive data entirely
class SecurePasswordManager {
    // SECURE: Use secure input methods instead of clipboard
    func copyPassword_secure4(password: String) {
        // DON'T copy passwords to any pasteboard
        // Instead: use password autofill, biometric authentication, or secure sharing
        print("❌ Not copying password to clipboard for security reasons")

        // Alternative: Use iOS Password AutoFill
        // Users can access passwords without clipboard exposure
    }

    // SECURE: Direct data transfer between screens
    func transferData_secure5(data: SensitiveData, to viewController: UIViewController) {
        // Pass data directly via properties, not clipboard
        if let targetVC = viewController as? DestinationViewController {
            targetVC.receivedData = data
        }
    }
}

// SECURE: Conditional pasteboard access with user awareness
class ConditionalPasteManager {
    func pasteWithUserConsent_secure6() {
        // Show alert asking user permission first
        let alert = UIAlertController(
            title: "Paste Content?",
            message: "Do you want to paste clipboard content?",
            preferredStyle: .alert
        )

        alert.addAction(UIAlertAction(title: "Paste", style: .default) { _ in
            // Only access clipboard after explicit user consent
            if let text = UIPasteboard.general.string {
                self.processText(text)
            }
        })

        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))

        // Present alert to user
        // (requires view controller context)
    }

    private func processText(_ text: String) {
        // Process pasted text
    }
}

// SECURE: Use iOS 14+ UIPasteboard detection APIs
@available(iOS 14.0, *)
class iOS14PasteboardDetection {
    func checkPasteboardAvailability_secure7() {
        // iOS 14+ provides methods to check clipboard without reading content
        if UIPasteboard.general.hasStrings {
            // Clipboard has strings, but we haven't read them yet
            print("Clipboard contains text (not read)")
        }

        if UIPasteboard.general.hasURLs {
            print("Clipboard contains URLs (not read)")
        }

        // Only read after user action (e.g., tapping paste button)
    }
}

Best Practices

Avoid general pasteboard for sensitive data:

// BAD
UIPasteboard.general.string = userPassword

// GOOD
// Don't use pasteboard for passwords at all
// Use iOS Password AutoFill or biometric authentication

Use named pasteboards with limited scope:

// Create app-private pasteboard
let privatePasteboard = UIPasteboard.withName(
    UIPasteboard.Name("com.example.app.private"),
    create: true
)!
privatePasteboard.isPersistent = false

Clear sensitive data immediately after use:

// Use and clear
privatePasteboard.string = temporaryData
processData()
privatePasteboard.items = []  // Clear immediately
  1. Use direct data transfer instead of clipboard:

// Instead of clipboard for inter-screen data transfer
class DataTransfer {
    var sharedData: Data?  // Direct property

    func passData(to destination: ViewController) {
        destination.receivedData = self.sharedData
    }
}

Implement clipboard monitoring detection (iOS 14+):

@available(iOS 14.0, *)
func detectClipboardAccess() {
    // Check type without reading content
    if UIPasteboard.general.hasStrings {
        // Ask user if they want to paste
        showPasteConfirmation()
    }
}

Comparison: General vs. Private Pasteboard

Approach Security Level Accessible by Other Apps?

UIPasteboard.general

⚠️ Dangerous

✅ Yes - all apps can read

UIPasteboard.general (iOS 14+)

⚠️ Risky

✅ Yes - with notification only

Named pasteboard + isPersistent = false

✅ Secure

❌ No - app-private only

No pasteboard (direct transfer)

✅ Most Secure

❌ No - data never in clipboard

Configuration

This detector reports the FIRST occurrence of UIPasteboard.general access in each source file. This approach:

  • Highlights files that use the general pasteboard

  • Avoids excessive noise from multiple usages in the same file

  • Allows developers to review and refactor entire files

The detector identifies these patterns:

  • UIPasteboard.general - Static property access

  • UIPasteboard.general.string - Reading string content

  • UIPasteboard.general.url - Reading URL content

  • Any property or method access on UIPasteboard.general

References