Photo library permission limited to selected photos on iOS 14+
Why it matters
iOS 14 introduced photo library limited access: users can grant access to a specific selection of photos rather than their entire library. An app that requests full photo library access for a feature that only needs one photo — such as a profile picture upload — forces users to choose between granting access to their entire camera roll or denying the feature entirely. This is a GDPR Art. 5(1)(c) data-minimisation violation. Apple's App Store reviewers check whether apps use the full library permission when limited access would suffice; requesting more than necessary is grounds for a guideline violation. CWE-272 (Least Privilege Violation) applies when an app acquires more access than its operation requires.
Severity rationale
Low because the over-permission is scoped to photo access rather than more sensitive data types, but it remains a GDPR Art. 5(1)(c) data-minimisation violation and a common App Store Review guideline failure.
Remediation
Use expo-image-picker with default settings for features that need one or a few photos — it automatically uses the limited access picker on iOS 14+. Only declare NSPhotoLibraryUsageDescription for features that browse the full library.
import * as ImagePicker from 'expo-image-picker'
// Profile photo upload: limited access is appropriate
async function pickProfilePhoto() {
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [1, 1],
quality: 0.8,
// On iOS 14+, this presents the limited-access picker by default
})
if (!result.canceled) {
uploadProfilePhoto(result.assets[0].uri)
}
}
In app.json, only add NSPhotoLibraryUsageDescription if a feature genuinely browses the full library. Use NSPhotoLibraryAddOnlyUsageDescription for save-only operations (e.g., saving generated images). Remove NSPhotoLibraryUsageDescription if all photo access goes through the picker.
Detection
-
ID:
photo-library-limited -
Severity:
low -
What to look for: Count all photo library access calls (ImagePicker, photo library APIs). For each, check whether the limited permission scope is used on iOS 14+. Check
Info.plistforNSPhotoLibraryUsageDescriptionvsNSPhotoLibraryAddOnlyUsageDescriptionentries. -
Pass criteria: If app accesses photo library, at least 100% of photo access calls use the limited permission (allowing users to select photos) when the feature only needs a single photo or a subset. Only full access is requested if the feature genuinely requires browsing all photos.
-
Fail criteria: App requests full photo library access for features that could work with limited access (e.g., profile photo upload). OR no photo library permission granularity is implemented on iOS 14+.
-
Skip (N/A) when: App does not access photo library (no photo picker or library import calls found), or targets pre-iOS 14 only.
-
Detail on fail: Quote the permission config.
"App requests full photo library access but only needs to upload a single photo (should use limited access)"or"Photo library permission not differentiated for iOS 14+ (user cannot choose selected photos)" -
Remediation: Use limited photo access on iOS 14+ to give users privacy control:
{ "app.json": { "ios": { "infoPlist": { "NSPhotoLibraryUsageDescription": "Select photos to share", "NSPhotoLibraryAddOnlyUsageDescription": "Save photos from the app" } } } }import * as ImagePicker from 'expo-image-picker' async function pickPhoto() { // This uses limited photo access on iOS 14+ const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsMultiple: false, }) }
External references
- cwe · CWE-272 — Least Privilege Violation
- gdpr · Art. 5(1)(c) — Data minimisation
- external · apple-photo-limited-access — Apple: Supporting Limited Photos Library in Your App (iOS 14+)
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mobile-permissions-privacy·automated