Service-account keys are a liability, not a convenience
This is a demo article showing the writeup format. Replace or delete it.
Long-lived credentials are the quiet failure mode of cloud security. Nobody decides to leave a powerful key lying around — it accumulates: a script needs access, someone exports a JSON key, it lands in a repo or a CI variable, and it never expires. From an attacker's seat, that key is often the whole game.
Why the key is the prize
A GCP service-account key is a static credential that authenticates as the service account — no MFA, no session, no user in the loop. If the account has broad roles, the key inherits all of them.
# What an attacker does the moment they find a key file:
gcloud auth activate-service-account --key-file=leaked.json
gcloud projects get-iam-policy $PROJECT # map what this identity can reach
The failure isn't the key existing — it's the combination: a static secret
- an over-privileged identity + no expiry + weak visibility into where it lives.
The three questions that matter
- Who can mint keys?
iam.serviceAccountKeys.createis the real perimeter. - What can each key do? Least privilege on the account, not just the human.
- Would you see it used? Key usage should be logged, alerted, and short-lived.
| Control | Weak | Strong |
|---|---|---|
| Credential | exported JSON key | workload identity / short-lived token |
| Scope | Owner / Editor | narrowly-scoped custom role |
| Lifetime | never expires | minutes, auto-rotated |
| Visibility | none | usage logged + alerted |
What to do instead
Prefer keyless paths — Workload Identity Federation, attached service accounts, and short-lived tokens minted per-use. Where a key is truly unavoidable, scope it hard, rotate it aggressively, and alert on its use from anywhere unexpected.
The goal isn't zero risk — it's removing the single artifact that turns a small foothold into full access.
Process over disclosure — this walks the shape of the problem, not any specific target.