Skip to content

Security: nicglazkov/gcloud-dot

Security

SECURITY.md

Security

Reporting a vulnerability

Email nic@glazkov.com, or open a private advisory. Please do not open a public issue for a vulnerability before it is fixed.

Expect a reply within a few days. There is no bounty; this is a free tool maintained by one person.

Trust model

GCloud Dot never handles your credentials. This is the decision everything else rests on. It does not read, copy, cache, or transmit tokens. It runs gcloud auth print-access-token and looks only at whether the command succeeded and, if not, which error it printed. The token is discarded without being examined.

It follows that compromising this app grants no credential it did not already have: anything able to run it could have run gcloud directly.

What it can reach

Reads gcloud's configuration directory, gcloud's command logs, and the application default credentials file, the last for its type and modification time, never its contents
Writes one JSON file in your own data directory, and a login item you control from the menu
Runs the gcloud binary, with no shell and no terminal window
Sends nothing, except the optional daily check of GitHub's public releases endpoint

No operating system permission covers any of that, which is why the app never asks for one. It is not sandboxed and does not claim to be.

The details window

Rendered in the system webview from HTML built inside the app. It loads no remote content and runs no script that did not ship in the binary. Every value originating outside the app, account address, project id, configuration name, is HTML-escaped before insertion, and a test fails if that stops being true. A configuration name is arbitrary text a user typed, so it is treated as hostile.

State file

Contains login timestamps, observed session lengths, notification bookkeeping, and settings. No credentials, no tokens, no key material. Run gcloud-dot paths to see its location.

Release integrity

  • macOS, signed with a Developer ID certificate, hardened runtime enabled, notarized by Apple. The app is stapled before the disk image is built, and the disk image is notarized and stapled in turn. Notarizing only the DMG would leave the app inside it without a ticket, which Gatekeeper hides by asking Apple online and which then fails for a user whose first launch is offline.
  • Windows, not code-signed. SmartScreen will warn. Verify the checksum.
  • All platforms, every release carries SHA256SUMS.txt, generated by the same workflow run that produced the binaries. Every artifact is built in public by GitHub Actions from a tagged commit.

Verify a macOS install:

spctl -a -vvv -t install "/Applications/GCloud Dot.app"
xcrun stapler validate "/Applications/GCloud Dot.app"

Dependencies

Deliberately few. The engine uses only serialisation and date handling. The tray adds the icon, menu, webview, and notification libraries it cannot reasonably reimplement. There is no HTTP client and no TLS stack in the tree: the update check shells out to curl, which every supported system ships, rather than linking a dependency tree larger than the rest of the app for one request a day.

Windows hardening rules

The app is designed to stay on the right side of Defender's attack surface reduction rules and of EDR heuristics generally, because a credential monitor that trips security tooling has failed at its one job of being trustworthy.

Concretely, nothing this project ships creates a process by way of WMI or PSExec, uses -EncodedCommand or -WindowStyle Hidden, or writes outside the user's own profile. The tray is started three ways only: the installer's finish page, the Startup folder shortcut, and, during a self update, the signed installer restarting it as its own child. All three give it an ordinary, explainable parent.

The one ASR block ever recorded against it came from this project's own remote test harness, which started the tray over SSH via Invoke-CimMethod on Win32_Process. That parents the process under WmiPrvSE.exe, which is exactly what the "block process creations originating from PSExec and WMI commands" rule exists to stop, and Defender was right to object. The harness uses the task scheduler now. No user-facing path was ever involved.

Known advisories

cargo audit runs in CI on every push, and fails the build on a vulnerability. As of 1.1.11 the tree has no known vulnerabilities. It carries thirteen warnings, and all but one of them are the same thing seen thirteen times.

GTK 3 bindings, unmaintained (ten crates: gtk, gdk, atk, their -sys companions, and gtk3-macros), plus glib 0.18.5, RUSTSEC unsoundness in VariantStrIter and proc-macro-error, unmaintained, which arrives as a build dependency of glib-macros.

All twelve reach the tree the same way, and only in Linux builds:

tao 0.36  ->  gtk 0.18  ->  glib 0.18.5
tray-icon 0.24  ->  libappindicator / muda  ->  gtk 0.18

Both of the crates this project depends on for a window and a tray icon pin GTK 3, so neither can be worked around by dropping the other. The fixes live in glib 0.20, which needs gtk 0.20, which needs releases of tao and tray-icon that have not happened. This cannot be resolved from here, and it will be picked up automatically when they move.

The unsound type is a GTK binding this project never names, directly or indirectly, and the flaw is unsoundness in an iterator rather than anything reachable from input.

ttf-parser, unmaintained. The only warning that is not about GTK, and the only one present on every platform. It arrives through ab_glyph, which draws the countdown text into the tray icon. It parses font files that ship inside the binary, so nothing an attacker controls reaches it.

Supported versions

The latest release. Fixes are shipped forward, not backported.

There aren't any published security advisories