The DigitalOcean metadata endpoint, and what SSRF gets from it

Any process on a Droplet can read its metadata with a plain HTTP request, and DigitalOcean documents no token to stop it. If your application can be tricked into fetching an attacker-supplied URL, the attacker can read it too.

Server-side request forgery, or SSRF, is a bug where an application fetches a URL on a user's behalf and the user chooses the URL. An image importer, a link preview, a webhook tester and a PDF generator all do it. The danger comes from where the request is made: from inside your server, where addresses are reachable that no outsider could touch.

The most famous such address on any cloud is the metadata endpoint. It deserves a closer look on DigitalOcean, partly for what it returns and partly for what it does not.

What the endpoint is

DigitalOcean's documentation describes the Droplet metadata service as living at a static link-local address, 169.254.169.254. You query it with a normal HTTP GET from the Droplet itself. The docs' own example is a single line:

curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/ipv4/address

There is no token and no special header in that example, and nothing in the documentation we read describes any authentication step. The property reference lists what is available, and /metadata/v1.json returns all of it as one JSON document.

A link-local address only has meaning on the machine's own network segment, which is why nobody outside can route to it directly. Only code running on the Droplet can reach it, and that includes code that has been tricked into making a request for someone else. That is the whole of the SSRF problem in one sentence.

What it returns

The documented properties include the Droplet's ID, hostname, region, public keys, vendor data, user data, tags, DNS settings, network interfaces with their public and private addresses, and any floating or reserved IP. Each one tells an attacker something.

  • User data is the one to worry about. DigitalOcean describes it as the data provided when the Droplet was created, and it can be a shell script or a cloud-config file. If a setup script ever contained a password, an API token or a database URL, it is sitting at /metadata/v1/user-data.
  • Interfaces and DNS reveal your private network addressing, which helps with the next step.
  • Tags often name the Droplet's role, such as web or db-primary, which tells an attacker which machines are worth targeting.
  • Public keys are public by design and add little.

The same user data how-to states that you cannot modify user data after a Droplet is created. So a secret placed there stays readable for the life of the Droplet, unless you rebuild it.

What an SSRF against it yields

Suppose your app has an endpoint that fetches a URL and returns the result. An attacker submits http://169.254.169.254/metadata/v1.json instead of an image address. The request comes from your Droplet, so the metadata service answers, and your app hands the response back.

On AWS this is the beginning of a serious chain, because the metadata service there can return temporary role credentials. The attack path analysis page uses that version as its worked example, and the AWS examples post walks the first path in detail. On DigitalOcean the picture is different, and it is worth being exact about how.

The documentation we read lists no endpoint that returns API tokens or role credentials. The documented properties are identity and configuration. That is a real difference from AWS, and it means a pure SSRF here does not, by the documented properties alone, give the attacker a key to your account.

It still matters, for two reasons. First, user data may contain exactly the secrets you thought were safe in a startup script. Second, an attacker who learns your private addresses and tags can aim the next request, often at an internal service that trusts anything on the private network.

What DigitalOcean does not give you

This is the honest gap. AWS added an optional session-token version of its metadata service so a simple forwarded request cannot read it. We found no equivalent in the DigitalOcean documentation, and no documented setting that turns the metadata service off for a Droplet. Whatever protects the endpoint on DigitalOcean has to come from you.

Blocking it with the Cloud Firewall is not a clean answer either. DigitalOcean's console documentation says the Droplet agent requires outbound TCP access to 169.254.169.254 to retrieve SSH keys, which implies outbound rules apply to that address and that blocking it would break the Droplet Console. We found no official iptables recipe for the endpoint either, so treat any firewall approach as something to test, not something supported.

Defences you control

  1. Do not fetch user-supplied URLs if you can avoid it. If the feature can take a file upload instead of a link, take the upload.
  2. If you must fetch, allowlist. Accept only the hostnames you expect. A blocklist of 169.254.169.254 is easy to get around.
  3. Check the address after resolving it. Resolve the hostname yourself, reject link-local and private ranges, and connect to the address you checked. A hostname can point at the metadata address, and a redirect can send you there after the first check, so apply the same test at every redirect hop.
  4. Keep secrets out of user data. This is our recommendation, not a DigitalOcean rule. Fetch secrets at deploy time from somewhere you control, so the metadata endpoint holds nothing worth stealing.
  5. Isolate the fetching code. A worker that downloads URLs should not share a machine, or at least not share secrets, with the rest of the application.

If you run DigitalOcean Kubernetes, there is documented help. The DOKS changelog for 11 August 2026 says it added a CiliumClusterWideNetworkPolicy that denies traffic to 169.254.169.254 on versions 1.36.3-do.1, 1.35.7-do.1 and 1.34.10-do.1. That implies pods could reach the endpoint before, so check which version your cluster runs. We found nothing in the App Platform documentation either way.

Testing your own application

If your app has a URL-fetching feature, test it yourself, on a system you own. Submit the metadata address and see what comes back. If you get JSON, the bug is real and the fixes above apply. If your app blocks the address by name, retry with a hostname you control that resolves to it, and then with a redirect. Most defences fail on the second or third try, not the first.

FAQ

Does the DigitalOcean metadata endpoint need a token?

The documentation shows plain GET requests with no token and describes no authentication step. We found no documented session-token option like the one AWS offers.

Does it give out API tokens like AWS gives out role credentials?

Not in the documented properties. They are identity and configuration data, including user data. That makes user data the main thing to protect.

Can I turn the metadata service off on a Droplet?

We found no documented setting for that. Blocking it with firewall rules is possible in principle, but the Droplet Console needs outbound access to it, so test carefully.

Is SSRF only a risk if I accept URLs from users?

Mostly, yes. Features that fetch a URL for a user, such as importers and previews, are where it appears. Any server-side fetch that a user can influence counts.

The attack path analysis page uses the AWS version of this problem as its worked example, and the DigitalOcean page covers what Secorvia reads from a connected account.

Keep reading
Examples · 7 min read

Four AWS attack paths, and the one change that breaks each

Fundamentals · 6 min read

What is an attack path in cloud security?

DigitalOcean · 5 min read

DigitalOcean API tokens: what a leaked one can reach

Try it against your own cloud account.