Are UUIDs Safe in URLs? Privacy and Access Control
Published
UUIDs can work well as public resource identifiers. The important design decision is what happens after someone obtains one: your application still needs to decide whether that person may access the resource.
A hard-to-guess ID is only one layer
Replacing sequential IDs with random identifiers makes simple enumeration harder. It does not fix missing authorization. OWASP's guidance on insecure direct object references recommends checking access to each object and scoping lookups to data available to the authenticated user.
For example, suppose an invoice endpoint receives a UUID in its URL. Looking up that invoice and returning it merely because the ID exists gives anyone who obtains the URL access. Instead, the lookup must apply the application's account, tenant, and permission rules before any invoice data is returned. Apply those rules to downloads and updates as well as the main detail page.
Know what the identifier reveals
UUID v4 has no embedded timestamp. UUID v7 exposes a millisecond timestamp; v1 and v6 contain time fields and may contain a MAC-derived node value, depending on the generator. These properties are documented in RFC 9562.
Consider a product that publishes links before an announcement. If approximate record creation times are sensitive, include identifier metadata in your privacy review. A decoded timestamp also should not be treated as proof of when an action occurred: the party generating the identifier controls its input.
Inspect non-sensitive samples with the UUID decoder or the v7 timestamp converter to see which fields are present.
Separate resource IDs from access tokens
An invoice ID should remain stable when someone revokes a sharing link. Model those as separate values: one identifies the invoice, while the other represents a specific grant of access. That separation lets you expire or revoke a grant without changing the record's identity or breaking internal references.
For password resets, invitations, and private sharing links, use your authentication framework's purpose-built token mechanism. Define its scope, expiration, revocation, and reuse policy explicitly. Do not assume that a value becomes a suitable secret merely because it looks like a UUID or passes a UUID validator.
Review the whole request path
- Verify that a signed-in user from another account cannot read, update, delete, or download the resource using a known valid ID.
- Check list, search, export, and attachment endpoints for the same access rules as individual resource pages.
- Review caches and logs so they do not expose private responses or secret sharing tokens to unintended readers.
- Treat client-supplied identifiers as untrusted input, even when they are syntactically valid UUIDs.
Choosing an identifier also involves storage and ordering tradeoffs. Read UUID v4 versus v7 for those decisions, and the collision guide for a separate look at uniqueness.
Browse all UUID articles →