NordVPN for macOS Stored Your Real IP and GPS in Plaintext
A VPN that cached the exact IP, coordinates, ISP and location it exists to hide, in world-readable files at rest, with no sandbox. Reported to Nord Security, HackerOne #3640402.
A VPN sells one promise: your real IP and location stay hidden. NordVPN for macOS wrote both to disk in plaintext, in world-readable files, with no sandbox in front of them. Any process running as the logged-in user could read the exact data the product exists to conceal.
This was reported to Nord Security on 31 March 2026 (HackerOne #3640402), assessed Low, and awarded a 100 dollar bounty. Two of the three findings were fixed in v10.4.0. The first one, the one that matters most, was still reproducing at last retest.
The finding
The affected build is the sideload distribution from nordvpn.com (v9.15.0, Build 352, Developer ID signed), not the Mac App Store version. It ships with no App Sandbox entitlement, which is what makes the rest of this reachable:
codesign -d --entitlements - /Applications/NordVPN.app 2>&1 | grep sandbox
# returns nothing
Without a sandbox, the app's files sit in the user's home directory at mode 644, readable by anything running as that user.
1. Real IP and geolocation in the URL cache, before you even sign in
On launch, NordVPN calls its own /v1/helpers/ips/insights endpoint and lets NSURLCache write the response to Cache.db. The response is your unprotected identity:
sqlite3 ~/Library/Caches/com.nordvpn.macos/Cache.db \
"SELECT receiver_data FROM cfurl_cache_receiver_data r
JOIN cfurl_cache_response c ON r.entry_ID = c.entry_ID
WHERE c.request_key LIKE '%insights%';"
{
"ip": "[REAL_IP]",
"city": "[CITY]",
"isp": "[ISP_NAME]",
"isp_asn": [ASN],
"protected": false,
"longitude": [REAL_LONGITUDE],
"latitude": [REAL_LATITUDE],
"zip_code": "[ZIP]"
}
This happens pre-authentication, and the file persists on disk across app restarts. It is not a transient in-memory value that clears on connect. The protected field also leaks whether the tunnel is currently up.
2. GPS coordinates in UserDefaults, after login
Once signed in, the raw coordinates land in the preferences plist (also mode 644):
defaults read com.nordvpn.macos 'AppCore.UserSession.latitude'
defaults read com.nordvpn.macos 'AppCore.UserSession.longitude'
These are full-precision floats. In testing they resolved to within roughly 100 metres of the real location, not a rounded city centroid.
3. Credential identifier written repeatedly to a readable log
The rotating logs under ~/Library/Caches/com.nordvpn.macos/Logs/ (mode 644) record which keychain entry holds the NordLynx WireGuard key:
[keychain] Password has been successfully saved for account: Password:nordlynxLogin:[CREDENTIAL_ID]
Twenty-nine instances appeared in a single session log. It is an identifier, not the key itself, but it points at the key and it is written into a file anything can read.
Why "it needs local code execution" is not a defence
The vendor's initial position was that reading the cache requires code running in the user's context, and so it does not cross a meaningful boundary. That reasoning does not hold for this product class.
A VPN's threat model is precisely the untrusted local process. Adware bundled with a free app, an npm package with a postinstall script, a browser extension's native helper, a piece of commodity malware. Those all run as the user, and hiding your IP and location from the network is the entire thing the VPN is paid to do. Storing that same data in cleartext at 644, unsandboxed, hands it back to every one of them. The protection is defeated locally by design, not by some exotic privilege escalation.
Disposition
Findings 2 and 3 were fixed in v10.4.0: the UserDefaults coordinate keys were removed and the credential logging stopped. Finding 1, the Cache.db cleartext IP and geolocation, was still present on v10.4.0 at retest on 24 June 2026, with coordinates at four decimal places (roughly 11 metre resolution).
The report was rated Low (3.3) and awarded 100 dollars. Nord declined to request a CVE for the cleartext-at-rest issue. The program later churned off HackerOne and the report was closed Resolved for reputation purposes, which the closing note explicitly stated is not a claim that the underlying issue is fixed.
The takeaway
Sandbox your app, or do not write secrets to the home directory. A privacy product cannot cache the very identifiers it exists to hide in a world-readable file and call the local attacker out of scope. The boundary a VPN defends is the one that starts at the untrusted process on the same machine.