DigitalOcean API tokens: what a leaked one can reach
A DigitalOcean personal access token acts as you. Make every token read-only or custom-scoped, give it an expiry, and keep a short list of which token lives where, because DigitalOcean will not hand you that list.
On a small team, one API token often ends up doing everything. It is created once, pasted into a CI secret, copied into a deploy script and into a laptop's shell profile, and nobody remembers what it can do. That is the token an attacker wants.
Three kinds of token
When you create a personal access token, DigitalOcean's token page offers three choices. Full Access is the api:write alias scope. Read Only is the api:read alias scope. Custom Scopes lets you pick specific scopes. Custom scopes are not new: DigitalOcean's API release notes record them as generally available in April 2024, after a beta in March.
Two details matter. First, you cannot edit the scope of a token after creating it, so a token that turned out to be too broad has to be replaced. Second, the options depend on your team role. The same page says that if a team owner restricts the permissions of your role, those permissions also disappear from your existing tokens. A token can never exceed the person who made it.
When a script needs only one job done, such as updating DNS records or listing Droplets, use Custom Scopes and grant that one thing. The extra minutes at creation are the whole price. A token that can only edit DNS is a nuisance if it leaks. A token that can delete databases is an outage, and a token cannot tell which of the two it was meant to be.
What a leaked full-access token reaches
DigitalOcean's scopes page says the write alias is equivalent to all scopes. In plain terms, a Full Access token can do through the API whatever its owner's role lets them do in the control panel. We found no single sentence in the documentation that lists every action, so read it as everything your role can reach: Droplets, databases, firewalls, DNS, and the rest.
There is one reach that surprises people. Spaces objects use separate access keys, not API tokens. But the API can create those keys. The Spaces keys API documents scopes for creating, reading, updating and deleting them. So a leaked token with the right scopes cannot read your bucket directly, yet it can mint a key that does. The Spaces article covers that side.
A read-only token is a very different thing. It can list and inspect, and it cannot create or destroy. That is why read-only is the right choice for anything that only needs to look, such as inventory scripts or a security scanner.
Expiry
The same token page says you choose when the token expires, and that after the interval passes it can no longer authenticate and disappears from your account. DigitalOcean added expiry intervals in February 2022.
The documentation we read does not list the exact intervals offered, and it does not say whether an option to never expire still exists. So open the creation form and look. Whatever the longest choice is, pick a shorter one than you think you need. A token with a 90-day lifetime that you rotate on a calendar is better than a perfect token you forget about.
Seeing which tokens exist, and when they were last used
The control panel's token table has a last-used column, and DigitalOcean's April 2022 blog post explains that the panel shows when a token was last used to access the API. The post adds that the new features apply to newly generated tokens, so an old token may show less. From the same menu you can rename, regenerate or delete a token, and the secret is shown only once, at creation.
Here is the limit. We found no API call or doctl command that lists your tokens, and the account API page documents a single account endpoint. So the control panel is the only list. The workaround is dull and works: give each token a name that says what uses it, such as ci-deploy-site, and keep your own short list of names, owners and renewal dates.
The team's Security History page records actions such as creating or deleting resources and API tokens, with the user, the originating IP and the time. It does not document logging each use of a token, so do not count on it to show you a leaked token being used. The last-used column is the closest signal.
If a token reaches a public repository
DigitalOcean's security page says that when GitHub detects a DigitalOcean token committed to a repository, DigitalOcean is alerted, the token is automatically revoked and the customer is notified. That is a good safety net for the most common leak. It covers one route only, and it does not help with a token pasted into a ticket, a chat or a public CI log.
In practice: CI and your own machine
For the command line, doctl auth init accepts a token, and the DIGITALOCEAN_ACCESS_TOKEN environment variable is honoured as well. doctl auth list shows the saved contexts and doctl auth switch --context <name> changes between them, so you can keep a read-only context for everyday work and a write context you rarely select.
doctl auth init --context readonly
doctl auth list
doctl auth switch --context readonly
Be careful with doctl auth token. Its own reference says to treat the output like a password, because it prints the saved token. For pipelines, DigitalOcean's GitHub Actions guides use a repository secret named DIGITALOCEAN_ACCESS_TOKEN with the digitalocean/action-doctl action. Use a separate token for each pipeline so you can revoke one without stopping the others.
A rotation routine that fits a small team
- Create a new token with the narrowest scope that works, and an expiry you will honour.
- Store it in the secret store of the one system that needs it.
- Run that system and confirm it works.
- Delete the old token in the control panel. Deleting revokes access, so anything still using it fails on its next request. That failure is the quickest way to find a forgotten copy.
- Update your list of names and renewal dates.
Treat any token that has ever been pasted outside a secret store, into a chat, a ticket or a shared document, as already exposed, and rotate it even if nothing looks wrong. A token you cannot account for is the same risk as one you know leaked, only quieter.
Do that for the Full Access token first. It is the one most likely to be pasted into several places, and the one that costs most if it leaks.
FAQ
Can I change a DigitalOcean token's scope after creating it?
No. DigitalOcean says you cannot edit a token's scope after creation, so create a replacement with the right scope and delete the old one.
Can I see when a token was last used?
Yes, in the control panel's token table. DigitalOcean added a last-used display in 2022, and it applies to newly generated tokens.
Is there a command to list all my tokens?
We found none. There is no documented API call or doctl command for it, so the control panel is the only list.
What does DigitalOcean do if a token is committed to GitHub?
Its security page says it is alerted by GitHub, revokes the token automatically and notifies the customer.
Secorvia's DigitalOcean connection guide asks for a read-scope token, which is the safest kind to hand to any tool. The DigitalOcean page covers the rest.