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:
-
Silent data access:
pasteText_vulnerable1()reads clipboard content without any indication to the user that their copied data is being accessed. -
Passive monitoring:
checkClipboard_vulnerable2()demonstrates how apps can read whatever users have copied, potentially exposing passwords, 2FA codes, or personal information. -
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. -
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. -
Automatic exploitation:
AutoPasteViewControllerdemonstrates 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
-
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? |
|---|---|---|
|
⚠️ Dangerous |
✅ Yes - all apps can read |
|
⚠️ Risky |
✅ Yes - with notification only |
Named pasteboard + |
✅ 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
-
CWE-200: Exposure of Sensitive Information to an Unauthorized Actor.
-
OWASP - Top 10 2021 Category A01 : Broken Access Control.
-
MASWE-0001: Insertion of Sensitive Data into Logs.
-
MASTG-KNOW-0083: Pasteboard.