CardPal Privacy Policy
Last updated: 2026-11-10
The short version
CardPal has no servers, no accounts, and no network code. Everything you put into it stays on your device. We — the developer — cannot see your documents, your numbers, or even that you use the app, because nothing is ever sent anywhere.
This is not a promise about how carefully we handle your data. It is a statement that we never receive it.
What we collect
Nothing.
CardPal collects no personal data, no usage analytics, no crash reports, no advertising identifiers, and no device identifiers. There is no sign-up, no login, and no account.
How you can verify that
You do not have to take our word for it:
- Every feature works with the network switched off. There is no account, no login, and no operation that needs a connection to complete. Turn on airplane mode, or block the app's network access in system settings, and nothing changes. That is a check you can run yourself, without trusting us.
- The app bundles no analytics, crash-reporting, advertising, or backend SDK. Its complete third-party dependency list is published below.
- About the Android
INTERNETpermission. The installed package does carry it, but CardPal does not declare it and does not use it: it is merged in at build time by a library the barcode scanner depends on (a data transport component of ML Kit). CardPal's ownAndroidManifest.xmldeclares only camera and notification permissions, and the app's code contains no network calls at all. We state this plainly rather than glossing over it — a privacy policy that claims the permission is absent, when the package plainly carries it, deserves less trust than one that explains where it came from.
What stays on your device
Everything you add:
| What | Where it lives | How it is protected |
|---|---|---|
| Document photos, file pages, and PDFs you stored as-is (passport data pages, ID cards, contracts, insurance policies, and so on) | A private folder inside the app's own sandbox | Encrypted with AES-256-GCM. The key is generated on your device and stored in the iOS Keychain / storage protected by the Android Keystore, hardware-backed where the device supports it |
| Card numbers, ID numbers and other main numbers; passport details (name, nationality, date of birth, sex); notes | A local SQLite database in the app's sandbox | Encrypted with AES-256-GCM before they are written, with the same device key as the photos |
| Entry names, tags, collection names (and each collection's icon, color, order and which cards are in it), family members' names, expiry dates | A local SQLite database in the app's sandbox | Stored as plain text, with no additional encryption — lists, search and expiry reminders need them; protected by the app's sandbox isolation and your device lock (biometrics / PIN) |
| Your app-lock PIN | iOS Keychain / storage protected by the Android Keystore | Stored only as a PBKDF2-HMAC-SHA256 hash with a random salt, never as the PIN itself |
| Your theme choice | Local app preferences | Not personal data |
| A file another app handed to CardPal through the share sheet, before you have filed it | Library/Caches/incoming/ in the container CardPal
shares with its share extension |
Not encrypted — it is not a CardPal record yet. That location is chosen deliberately: it is the one place that does not go into an iCloud or iTunes backup. See "Files shared in from other apps" below |
The device key stays on this device: it never leaves in a backup or any other way, and a backup file is encrypted with its own password instead (see "Backups" below). The same list is in the app, under Settings → Security → What's encrypted.
A PDF is encrypted exactly like a photo. A "file" entry can hold a PDF as it is, without converting it to images; it uses the same device key and the same encryption as the photos. If the PDF carries its own open password, CardPal does not store that password — it stays in memory only while you have the file open, is gone the moment the app locks or quits, and you type it again next time. That is deliberate: somewhere that remembers the password to your insurance policy is somewhere worth stealing.
Photos taken in CardPal are never written to your system photo library. The built-in camera writes straight into the encrypted store, and the camera plugin's temporary file is deleted immediately afterwards. The one thing you can put in your library is a document copy you made yourself, and only by choosing "Save Image" in the share sheet — see "A document copy leaves the encrypted store" below.
You can send a photo out yourself. That is the only way one leaves this device unencrypted and unchanged. While you are looking at a photo there is a Share button, which hands that one photo to the system share sheet — AirDrop it to your own Mac, attach it to an email, send it to whoever asked for it. It happens only when you tap it, and only for the photo on screen. (Photos also travel inside an encrypted backup, and a document copy you make is a watermarked rendering of one; both have their own section below.) CardPal takes "Save Image" off that sheet, so it offers no one-tap route from an original into your photo library. The sheet's other destinations belong to iOS and to the apps you installed; what they do with the file is between you and them.
Permissions we ask for, and why
| Permission | Why | What happens if you decline |
|---|---|---|
| Camera | To photograph a document's data page, and to scan a loyalty card's barcode | You can still add everything by typing it in |
| Face ID / Touch ID / fingerprint | To unlock the app | You unlock with your PIN instead |
| Notifications | To remind you before a document expires | You get no reminders; the home screen still warns you when you open the app |
Beyond those, CardPal asks for no contacts, no location, no microphone, no network permission, and no exact-alarm permission.
The photo library: CardPal's own code never calls a photo-library API, not once. You will, however, see two "Photos" purpose strings in CardPal's iPhone settings or its App Store listing. They mean different things, and both are described here:
- "Add to photo library." There is exactly one situation that uses it: you made a document copy and chose "Save Image" in the share sheet. You start that, iOS confirms it on your behalf, and the only thing written is that one watermarked copy. CardPal never writes an original that way — when you share one, "Save Image" is taken off the sheet.
- "Access the photo library." This one is never triggered. It has to exist because the photo-picking component CardPal uses also contains code for full library access, and Apple rejects an app whose binary references that code without a purpose string. CardPal never calls it; the string describes only the system picker below.
Choosing a photo you already have. To add a document from a photo already on your phone, CardPal opens the system photo picker. The picker runs outside CardPal: you browse your library there, and CardPal receives only the photos you tap — it never sees the rest of your library, and you are never asked to grant library access. CardPal strips the location and other metadata from a picked photo and encrypts it like a photo taken in the app.
Expiry reminders are scheduled by your device's own operating system and never involve a server. Their text deliberately carries only a count and a number of days — never a document's name, number, or owner. It appears on your lock screen, and iOS gives an app no way to hide that preview, so the only reliable protection is for the text to hold nothing worth hiding.
Biometric matching is performed entirely by your operating system. CardPal receives only a yes-or-no answer; it never sees your face or fingerprint data.
What the show screen can and cannot stop
When you show a document, CardPal asks Android to block screenshots and screen recording of that screen, and reports it only after the system confirms it. iOS provides no equivalent, so on iPhone a screenshot of that screen cannot be stopped. While the screen is being recorded or mirrored (including AirPlay), though, the show screen covers the card with an opaque notice. Both platforms still get the app-switcher mask, and the app lock if you have it on.
CardPal says nothing on screen while these protections are working — a badge that is always on is noise. It warns you only when a protection it promised is not in effect, because that is the case you might act on.
Document copies leave encrypted storage — on purpose
A document copy is the one thing CardPal produces that is not encrypted: it is a plain PNG or PDF, because the point is to hand it to someone or upload it.
- You decide where it goes. When it is ready there are two actions: Save (to a location you pick) and Share (hand it to the system share sheet). Both take a deliberate tap; CardPal never sends it anywhere on its own.
- The share sheet lets you pick "Save Image", which puts the copy in your photo library. That is your choice, not something CardPal does — it only hands the file to the system. CardPal never puts an original there itself: when you share an original (see the paragraph after this list), "Save Image" is taken off that sheet, and CardPal neither has nor asks for permission to write an original to your library (see "Photos taken in CardPal are never written to your system photo library" above).
- While sharing, CardPal briefly places a copy in the phone's temporary folder and deletes it as soon as the sheet closes; it sweeps again at the next launch in case that did not happen.
- The shared file is not named after your entry. It
is called
copy-<date>, notMum's passport-<date>— that name is one you chose for yourself, and it has no business travelling into someone else's inbox. Your own Save still uses the entry title. - Once saved, that file is outside CardPal's protection. Your phone's own backups, cloud sync, or anything else with file access can read it.
- The watermark exists for exactly this reason. Naming what the copy is for, and the date it was made, is what stops a leaked sheet being reused for something else. Filling in the purpose is optional, and it is the single most useful thing you can do to protect a copy.
- CardPal keeps no record of copies you have made.
Sharing a photo itself works the same way, with two
differences. A copy is not the only thing you can hand out:
while you are looking at a photo you can share that photo as it is.
Everything above applies — you tap it, CardPal puts a single unencrypted
file in the temporary folder, hands it to the system sheet, deletes it
when the sheet closes, and names it photo-<date>
rather than after your entry. The two differences: that file has
no watermark, because it is your photo rather than a sheet made
to be handed over; and "Save Image" is removed from that
sheet, so CardPal offers no one-tap route from an original into
your photo library. Once it is out, it is outside CardPal's protection,
the same as a copy.
Files shared in from other apps
CardPal registers an entry in the system share sheet, so an insurance policy you are looking at in a messaging app, in Mail, or in Files can be sent straight to CardPal. A few things about that path are worth knowing:
- A file that has just arrived is not encrypted yet. It is not a CardPal record at this point — only when you next open CardPal, fill in the form that pops up and save it does CardPal encrypt it into the vault and delete the original.
- Its landing place is deliberately one that does not get
backed up. It sits under
Library/Caches/in the container CardPal shares with the extension, not underDocuments/— the latter goes into iCloud and iTunes backups. An unencrypted policy sitting in a backup would travel further than it ever does inside CardPal. The cost: the system is allowed to clear that folder when disk space runs short, so a file you shared but never opened CardPal to file can disappear. If that happens, share it again. - The extension cannot open CardPal. That is an iOS restriction, not laziness. So all it can do is tell you it got the file; the form waits until you next open CardPal yourself.
- "Erase all data" clears these unfiled files too. Otherwise that plaintext would survive the erase and be offered, at the next launch, to whoever uses the phone next.
- The extension has no networking ability, exactly like the app itself, and sends files nowhere.
Backups — the one place data leaves the app
CardPal can export an encrypted backup file. This only ever happens when you ask for it. Three things to understand:
- You choose the password. The file is encrypted with a key derived from it (PBKDF2-HMAC-SHA256, 600,000 rounds for new backups, then AES-256-GCM; the round count is stored in the file, so older backups made with fewer rounds still open). CardPal does not store that password and cannot recover it. If you lose it, the backup can never be opened — not by you, and not by us.
- You choose where the file goes. You pick the destination in your system's file picker. If you choose a cloud folder (iCloud Drive, Google Drive, Dropbox), the file is then subject to that provider's privacy policy, not this one. The file itself remains encrypted.
- The backup contains your document photos and PDFs. That is the point of it — a backup without them would not restore your documents. Treat the file as sensitive. (Files shared in but not yet filed are not in a backup: they are not CardPal records yet.)
Forgetting your PIN
If you forget your PIN there is no recovery path, because there is no server holding a copy. The app offers a factory reset that erases all local data after a 24-hour delay; entering the correct PIN at any point in those 24 hours cancels it. The delay exists so that someone who takes your phone cannot wipe it instantly.
Children
CardPal is a personal utility with no accounts, no social features, no messaging, and no data collection. It is not directed at children, and because it collects nothing, it collects nothing from children either.
Third-party components
CardPal is built with Flutter. These are all of its direct dependencies:
provider · sqflite · path ·
path_provider · flutter_slidable ·
barcode_widget · uuid ·
shared_preferences · file_picker ·
image_picker · local_auth ·
cryptography · flutter_secure_storage ·
camera · mobile_scanner ·
screen_brightness ·
flutter_local_notifications · timezone ·
archive · pdf · pdfrx ·
cupertino_icons · characters ·
flutter_localizations · intl
Those packages pull in lower-level ones of their own. One is worth
naming: pdfrx (which displays PDFs) brings in
url_launcher, whose job is to open links inside a PDF —
CardPal turns the PDF reader's link handling off
entirely, so it is never used here.
Nothing anywhere in that dependency tree is an analytics, advertising, attribution, or backend SDK, and none of it transmits your data. You do not have to take that on trust: the airplane-mode check under "How you can verify that" above says more than any list can.
Your rights
Because we hold no data about you, there is nothing for us to disclose, export, correct, or delete on your behalf. You already hold all of it, and deleting the app deletes it.
If you are covered by the GDPR, the CCPA, or a similar law: we are not a controller or processor of your personal data, because we never receive it.
Changes to this policy
If a future version of CardPal changes what leaves your device, this policy will be updated before that version ships, and the change will be described in the app's release notes. We will not quietly add data collection to an app sold on the promise that it has none.
Contact
Questions about this policy, or about anything in the app: stephen.li@wdbible.org