The vulnerability in gittuf allows an attacker with push access to the Reference State Log (RSL) to roll back the security policy to a previously valid version. This is a logic flaw in the policy verification process. When a new policy is introduced, gittuf is supposed to verify it. However, the verification logic was missing a crucial step: checking if the 'new' policy was actually older than the current one.
The vulnerable function is policy.State.VerifyNewState, located in internal/policy/verify.go. This function is called to validate a new policy state. Before the fix, it would check signatures and other validity criteria but failed to compare version numbers. An attacker could create a new RSL entry pointing to an old policy commit, and VerifyNewState would approve it as long as it was signed by keys trusted by the current policy.
The patch addresses this by introducing a monotonically increasing version number in the policy metadata. The VerifyNewState function was modified to call a new function, VerifyNewStateMetadata, which explicitly checks that the version of the incoming policy is greater than or equal to the version of the current policy. If this check fails, it returns a new ErrMetadataRollbackDetected error, preventing the rollback attack.