How TUF Rejects Old, Mixed, and Wrong Updates

TUF's architecture becomes meaningful only when a client uses it as an ordered validation process. This chapter follows that process from a trusted root to a fetched target and matches each check to the failure it is meant to prevent. The central distinction is between authenticity and currentness: a signature can identify an authorized signer, but versions, expiration, hashes, and metadata relationships determine whether the signed statement is the right one to use now and whether its target belongs to a coherent repository state.

From trusted root to an accepted target

The client begins by fixing the update start time. That may sound like a minor implementation detail, but it gives the rest of the workflow one stable point of comparison. If an update takes long enough for metadata to expire halfway through, the client should not get a different answer merely because the clock advanced during the same update attempt. The fixed time lets the client judge whether metadata was valid when the update began.

The client then loads a trusted root file that was supplied out of band. The initial root is special: its trust comes from the way the updater was delivered, not from the repository it is about to contact. The client does not simply replace that root with the newest file offered by a mirror. It tries to advance through successive root versions, preserving a verifiable line of continuity.

Suppose the client trusts root version N. It requests version N+1, using a versioned filename and a bounded download size. The new root must be signed by the required threshold from the old root and by the required threshold specified in the new root. The first condition prevents a repository from inventing a new authority without consent from the authority already trusted. The second condition shows that the proposed new configuration has the support it claims for itself. If the checks pass, the client persists the new root and repeats the process while the next version is available.

This incremental transition explains why key rotation is not a special escape hatch from verification. A client that is several root versions behind can still retrace the sequence, provided the repository retains the intermediate roots. If an attacker supplies an older root, version ordering rejects the rollback. If the latest available root has expired by the fixed update start time, the client reports a potential freeze rather than silently treating an old trust configuration as current.

After root continuity is established, the client downloads timestamp metadata. Timestamp is deliberately small and focused: it describes the current snapshot metadata, including its version and, when used, its length and hash. The client verifies the timestamp signature against the role authorized by the trusted root. It also checks that the new timestamp is not older than the timestamp already trusted and that the snapshot version it names has not moved backward.

Timestamp therefore does two jobs that should not be confused. Its expiration provides a freshness deadline for the repository's current statement. Its reference to snapshot identifies which coherent repository state the client should fetch next. A timestamp key may be online and frequently refreshed, but it does not directly authorize an executable.