Skip to content

Security review: credential exposure, browser hardening, dependency and map access concerns #214

Description

@LanKing

Hi,

First of all, thank you for building this integration.

I did a security-oriented review of the current 1.7 branch because this integration has a considerably higher trust level than a typical Home Assistant custom component: it processes Google authentication material, device/location data, and runs inside the Home Assistant Python process.

I want to be clear about the scope of this report:

I did not find evidence of an intentional backdoor, credential exfiltration to the project author, or deliberately malicious behavior.

I am posting this publicly because I did not identify an active credential leak or a directly exploitable backdoor. If you believe any of the findings should be handled privately, feel free to hide/remove this issue and I can continue through a private channel.

The concerns below are mostly about reducing the blast radius if Home Assistant, a dependency, the browser automation chain, or a URL/token gets compromised.

Some of these are hardening recommendations rather than confirmed exploitable vulnerabilities. I have marked them accordingly.


Summary

Finding Severity Type
Chrome launched with sandbox/web security disabled High Confirmed hardening issue
undetected_chromedriver / driver download chain in trusted auth workflow High Supply-chain / architecture risk
Sensitive Google credential bundle persisted in HA High Credential exposure / blast radius
Broad non-pinned runtime dependencies Medium Supply-chain risk
Map access via capability token instead of normal HA authentication Medium Access-control design
Long-lived/deterministic map token Medium Token management
Location map loads third-party JS/resources Medium Privacy / supply-chain
Broad Chrome process termination Low–Medium Host impact
Sensitive data may reach logs through exceptional paths Low–Medium Information disclosure
Security expectations are not fully documented Medium Documentation / user-risk

1. Chrome is launched with important security protections disabled

Severity: High

Relevant code is in the Chrome/WebDriver setup.

The current options include:

chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-web-security")
chrome_options.add_argument("--allow-running-insecure-content")

Why this matters

These switches significantly reduce Chrome's normal security boundaries.

--no-sandbox is especially relevant if untrusted browser content is ever processed.

--disable-web-security disables browser-origin protections that normally isolate websites from each other.

--allow-running-insecure-content permits insecure active content in contexts where Chrome would normally block it.

For an authentication workflow handling Google credentials, this creates a larger blast radius if:

  • Chrome/Chromedriver has a vulnerability;
  • navigation is redirected unexpectedly;
  • a page loaded during authentication becomes compromised;
  • a dependency manipulating the browser becomes compromised.

This does not mean the current integration is exploiting these flags maliciously. The concern is defense in depth.

Recommendation

Remove all three unless there is a demonstrated requirement.

Ideally the base configuration should be closer to:

chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--disable-dev-shm-usage")

If --no-sandbox is unavoidable in a particular environment, document why it is required and avoid disabling web security at the same time.

In particular, I would strongly recommend removing:

--disable-web-security
--allow-running-insecure-content

even if --no-sandbox must temporarily remain.


2. Browser automation is part of a very high-trust credential chain

Severity: High
Type: supply-chain / architectural risk

The integration depends on:

selenium
undetected_chromedriver

and has fallback/browser-driver management logic.

Why this matters

undetected_chromedriver is not comparable to a small pure-Python utility dependency.

Its purpose involves managing and modifying the Chrome/ChromeDriver execution environment.

That means the trust chain effectively becomes approximately:

Home Assistant
    ↓
GoogleFindMy integration
    ↓
Python package index / package dependencies
    ↓
undetected_chromedriver / driver tooling
    ↓
ChromeDriver executable
    ↓
Chrome
    ↓
Google authentication session

This is a significant amount of trusted code around very sensitive authentication material.

A supply-chain compromise anywhere in this chain would potentially have access to an authenticated browser session or local credentials.

Recommendation

The strongest design would be to completely separate browser-based authentication from the Home Assistant runtime.

For example:

External authentication/setup utility
              ↓
        Google login
              ↓
      credential bundle
              ↓
Home Assistant GoogleFindMy integration

The Home Assistant integration itself would then only contain the API client and would not require:

selenium
undetected_chromedriver
webdriver-manager
Chrome
ChromeDriver

This would substantially reduce the trusted computing base.


3. Highly sensitive Google credentials are persisted inside Home Assistant

Severity: High

The integration needs and stores authentication material derived from the supplied secrets bundle, including Google/Android-related authentication state such as OAuth/AAS/FCM-related credentials.

The token cache also persists authentication state using Home Assistant storage.

Why this matters

This is probably unavoidable to some degree, but users should understand the consequence:

A compromise of the Home Assistant host may become a compromise of active Google authentication credentials.

This is substantially more sensitive than a normal entity/API integration token.

Threat scenarios include:

  • malicious custom component;
  • compromised Home Assistant add-on with filesystem access;
  • stolen HA backup;
  • exposed /config/.storage;
  • local host compromise;
  • supply-chain attack affecting another Python dependency running in the same process.

I have not confirmed that the stored credential set alone is sufficient for complete Google Account takeover, password change, or Gmail/Drive access.

However, it appears sufficiently privileged to impersonate parts of an authenticated Android/Find My client, so the impact of theft should be treated as potentially serious.

Recommendation

Minimize what is stored

Store only the fields required at runtime rather than preserving the full original secrets bundle when possible.

Separate credentials by purpose

Avoid keeping setup-only authentication artifacts after setup is complete.

Clearly document the threat model

Users should be told explicitly:

This integration stores sensitive Google authentication material inside Home Assistant. Any component, backup, administrator, or process with access to Home Assistant's configuration storage may potentially obtain these credentials.

Document revocation

Provide an explicit "If these credentials are exposed" section explaining exactly how users can revoke them.


4. Dependency versions are broad rather than tied to a reviewed dependency set

Severity: Medium

The manifest currently contains requirements in forms such as:

aiohttp>=...
cryptography>=...
gpsoauth>=...
protobuf>=...
selenium>=...
undetected_chromedriver>=...

Why this matters

This means the exact executable dependency set is not necessarily identical for every installation of a given integration release.

In principle:

GoogleFindMy version X

could remain unchanged while a new dependency version begins being installed.

For security-sensitive dependencies this makes reproducibility and security review harder.

The most relevant packages are those that:

  • process credentials;
  • perform cryptography;
  • communicate with Google;
  • start external processes;
  • download or control browser components.

Recommendation

At minimum:

  • use sensible upper bounds for sensitive dependencies;
  • test an explicit dependency matrix before releases;
  • use dependency update automation;
  • run vulnerability scanning in CI;
  • document dependency upgrades in release notes.

For especially sensitive dependencies, consider exact versions if compatible with Home Assistant packaging policy.


5. Map access should preferably use native Home Assistant authentication

Severity: Medium

The map/history view currently uses a capability-token-style access model rather than relying exclusively on normal authenticated Home Assistant access.

Why this matters

A capability URL effectively behaves like:

Anyone possessing this URL/token can access this resource.

This is useful for sharing, but dangerous for precise location history.

Capability tokens can leak through:

  • browser history;
  • copied URLs;
  • screenshots;
  • reverse proxy logs;
  • analytics;
  • HTTP logs;
  • referrer handling;
  • support reports.

This risk is particularly important because the protected resource is location data.

Recommendation

For normal map usage:

requires_auth = True

and rely on Home Assistant's existing authenticated session.

If shareable links are intentionally supported, make them a separate explicit feature.


6. Capability tokens should be random, revocable and expire

Severity: Medium

If capability URLs remain supported, their tokens should be treated exactly like credentials.

Recommendation

Generate them from a cryptographically secure RNG, for example conceptually:

secrets.token_urlsafe(32)

Additionally:

  • use at least ~128 bits of entropy, preferably 256;
  • support expiration;
  • support manual revocation;
  • regenerate on revoke;
  • store only a hash of the token where practical;
  • never emit the token in logs;
  • avoid query strings where possible.

A token should not remain valid indefinitely by default.


7. The location map should not execute third-party JavaScript if avoidable

Severity: Medium

If Leaflet or another JavaScript dependency is loaded from a public CDN, that CDN becomes trusted code running in a page that has access to location information.

Conceptually:

Location history
      ↓
Browser page
      ↑
Third-party JavaScript CDN

Why this matters

A compromised CDN/package/version could execute arbitrary JavaScript in the map context.

Even if this is unlikely, location history is sensitive enough that this dependency is unnecessary.

Recommendation

Bundle a reviewed version of Leaflet directly with the integration:

custom_components/googlefindmy/www/leaflet/
    leaflet.js
    leaflet.css

Use local static resources instead of remote executable JavaScript.


8. Map tile providers create a privacy side channel

Severity: Medium / privacy

Even if exact device coordinates are never intentionally transmitted to another API, an external tile provider receives requests for map tiles.

Those requested tiles necessarily reveal the approximate geographic area being viewed.

Therefore a statement equivalent to:

Location data is never transmitted to third parties.

may be too strong if external map tiles are used.

Recommendation

Document this precisely.

For example:

Device coordinates are processed locally and are not intentionally uploaded to the integration author. When the built-in map is used, the configured map tile provider receives tile requests corresponding to the geographic area displayed.

Optionally support user-configurable/local tile sources.


9. The integration should not terminate unrelated Chrome processes

Severity: Low–Medium

There is logic that uses commands equivalent to:

taskkill ... chrome.exe

or:

pkill -f chrome

Why this matters

That can affect Chrome processes not created by this integration.

On a shared host or development machine this could:

  • terminate unrelated browser sessions;
  • interrupt other automation;
  • cause data loss;
  • interfere with another service.

Recommendation

Track the PID/process group created by the integration and terminate only that process tree.

Avoid global Chrome process cleanup.


10. Logging paths should assume all authentication payloads are secrets

Severity: Low–Medium

The code already contains several positive security practices around redacting Bearer tokens and sensitive values.

That is good.

However, exceptional authentication/browser paths should also avoid logging:

  • browser alert contents;
  • raw Google responses;
  • token exchange responses;
  • entire dictionaries received during authentication;
  • FCM registration data;
  • AAS/ADM/OAuth values.

Recommendation

Use a single centralized redaction helper and make logging fail closed.

For example:

LOGGER.debug("Authentication failed: %s", sanitized_error_type)

rather than serializing remote payloads.

It may also be useful to add tests asserting that known secret patterns never appear in captured logs.


11. Please document the security boundary explicitly

Severity: Medium from a user-risk perspective

This integration is fundamentally different from many Home Assistant integrations.

A normal integration may have a limited API key.

This one may possess authentication material representing an authenticated Google/Android client and location history.

That makes the trust decision much more important.

I would suggest adding a dedicated README section such as:

Security considerations

with something like:

This integration stores sensitive Google authentication credentials in Home Assistant so it can access Google Find My services.

Install only on a Home Assistant instance you trust.

Any administrator, custom integration, malicious dependency, backup recipient, or attacker with sufficient access to Home Assistant's configuration may potentially access these credentials.

Do not share diagnostic files or .storage contents without verifying that authentication material has been removed.

That would make the project's security model much clearer.


Positive findings

I also want to mention several things I specifically looked for and did not find.

During the review I did not identify:

  • an author-controlled credential exfiltration endpoint;
  • obvious Telegram/Discord/webhook exfiltration;
  • intentionally obfuscated payloads behaving like a backdoor;
  • obvious eval()/arbitrary Python execution used to hide remote code;
  • hidden persistence mechanisms;
  • code intentionally sending location history to the project author.

There is also already code attempting to redact sensitive values from logs and to scope credential storage to Home Assistant's storage facilities.

So this report should not be interpreted as an accusation of malicious behavior.

The main concern is that the integration processes unusually valuable credentials, and therefore deserves a stricter security posture than a typical Home Assistant custom component.


Suggested priority

If only a few changes can be made initially, I would prioritize them as:

P0

  1. Remove --disable-web-security and --allow-running-insecure-content.
  2. Re-evaluate whether --no-sandbox is genuinely required.

P1

  1. Move Selenium / undetected_chromedriver authentication out of the Home Assistant runtime.
  2. Use normal Home Assistant authentication for the location-history UI.
  3. Make any sharing tokens random, expiring and revocable.

P2

  1. Bundle map JavaScript locally.
  2. Tighten sensitive dependency version ranges.
  3. Minimize persisted credential material.
  4. Improve security/threat-model documentation.
  5. Add automated tests ensuring secrets never reach logs.

One question that would help assess the impact

The remaining security question I could not answer conclusively from the integration alone is:

What is the maximum privilege obtainable from a stolen secrets.json / persisted AAS/OAuth/FCM credential bundle?

In particular:

  • Can it authenticate only to Find My-related Android APIs?
  • Can it access other Google account APIs?
  • Can it create or refresh broader Google authentication tokens?
  • Can it survive a Google password change?
  • What is the correct server-side revocation procedure?
  • Can a stolen credential bundle contribute to a complete Google account takeover?

Documenting this would be extremely valuable because it determines the real severity of a Home Assistant credential leak.

Thanks for considering the report.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions