The one-sentence version
In security incidents, the most common amplifier is not "how deep the vulnerability is," but "how many doors the stolen key can open." The Principle of Least Privilege states: every person, every program, and every token should possess only the minimum permissions necessary to perform its job. In engineering terms, this boils down to three things: narrow token scopes, no plaintext keys lying on disks, and isolation between services. This way, even if one point is compromised, the damage is contained within that single door.
This article has three layers:
- Layer 1: The Intuition: Why master keys are dangerous
- Layer 2: Real-World Use: Real incidents like Codecov, CircleCI, Uber, and Badger DAO
- Layer 3: Principles and engineering key points: narrow-permission tokens, key storage, service isolation, and rotation
Layer 1: The Intuition
1.1 The Master Key
In an office building, a janitor only needs access to the hallways and restrooms. If, for the sake of convenience, they are given a master key, then once that key is lost, the safes, server rooms, and archives of the entire building are exposed.
In the software world, "master keys" are everywhere:
- A cloud platform API token that can change DNS, modify websites, change email forwarding, and delete databases;
- A server running a dozen services, all running with root privileges;
- A
.envfile containing all passwords for all services, stored in plaintext on a developer's computer.
1.2 The Meaning of Least Privilege
In 1975, Saltzer and Schroeder listed it as one of the fundamental principles of secure design in their classic paper, The Protection of Information in Computer Systems:
Every program and every user should use only the minimum permissions necessary to complete their task.
It cannot prevent a key from being stolen, but it determines how much damage is caused after the key is stolen.
Layer 2: Real-World Use
| Event | Process | If Least Privilege was applied |
|---|---|---|
| Codecov (2021) | Attackers tampered with an upload script used by many CI pipelines, causing the script to exfiltrate CI environment variables (containing various cloud service credentials) | If only the credentials necessary for that specific step were placed in the CI environment, the exposure surface would have been much smaller |
| CircleCI (2023) | An engineer's computer was infected with malware and the session was stolen, allowing attackers to access customer keys stored on the platform; the platform required all customers to rotate all keys | Sensitive credentials should be stored hierarchically and be short-lived |
| Uber (2022) | After entering the internal network, attackers found a script with hardcoded administrator credentials in a network share, gaining access to many internal systems | Credentials should not be written into scripts; administrator privileges should be requested on-demand |
| Badger DAO (2021) | Attackers obtained a Cloudflare API key and injected a malicious script into the DeFi frontend, resulting in a loss of approximately $120 million | Deployment tokens should only be able to modify specific sites and should have version monitoring (see "Bybit Incident and Frontend Integrity") |
Layer 3: Principles and Engineering
3.1 Narrow Tokens
Modern cloud platforms almost all support fine-grained permissions. Create a separate token for each specific purpose:
| Purpose | Required Permissions | Prohibited Permissions |
|---|---|---|
| Deploy Frontend | Can only update a specific site or script | Changing DNS, changing email, managing accounts |
| Monitoring | Read-only | Any write permissions |
| Emergency Shutdown | Can only remove a specific route | Modifying page content |
Additionally: Set expiration times; restrict by source IP where possible; clearly name tokens by their purpose to facilitate future auditing and revocation.
3.2 Do Not Leave Keys in Plaintext on Disks
| Storage Method | Risk |
|---|---|
| Written in code, committed to Git | Worst case: Leaked if the repository is public or cloned; impossible to completely erase from history |
| Plaintext files in the home directory | Any program running as you (including malicious npm packages or browser extensions) can read them |
| System Keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service) | Stored encrypted; may require authorization when reading; retrieved only when needed |
| Dedicated Key Management Services (Vault, Cloud KMS, Secrets Manager) | Ideal for servers: centralized management, auditing, and automatic rotation |
A practical tip: When saving a token, have the script read it from the clipboard and write it directly to the keychain so the token never appears on the screen, in terminal history, or in chat logs.
3.3 Service Isolation
- Run each service using a unique system user rather than root or a shared account;
- The code directory should be owned by root and read-only; the data directory should only be read/write by the service's own user (permissions
0700/0600); - Each service should have its own configuration and key files, rather than sharing one large
.env; - Services that hold a private key or handle money should run on a dedicated machine, isolated from other services.
This way, if one service is compromised, the attacker only gains the permissions of that specific service user and cannot read the keys of neighboring services.
3.4 The Overlooked Link: The Developers Themselves
The starting point for many supply chain attacks is not the server, but the developer's computer (as seen with Bybit and CircleCI). Developers' computers often store the highest-privilege credentials. Countermeasures:
- Enable strong two-factor authentication (preferably passkeys or hardware keys) for all cloud accounts, code hosting, and domain registrars;
- Use short-lived credentials for high-privilege operations, which expire immediately after use;
- Lock deployment tool versions; do not download the "latest version" every time you run them.
Summary
| Layer | Key points |
|---|---|
| Principle | Give only the minimum permissions required to complete the work; damage is limited if a key is lost |
| Token | One token per purpose; prioritize read-only; set expiration |
| Storage | No code commits, no plaintext files; use keychains or KMS |
| Isolation | Independent system users, independent file permissions; services handling money should have dedicated machines |