{"record":{"id":"7177ee5b1b87a5a9","repo":"docker/cli","slug":"warning-potential-malicious-behavior-trust-data-7177ee","errorCode":null,"errorMessage":"warning: potential malicious behavior - trust data version is lower than expected for remote repository %s: %v","messagePattern":"warning: potential malicious behavior - trust data version is lower than expected for remote repository (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cmd/docker-trust/internal/trust/trust.go","lineNumber":250,"sourceCode":"func NotaryError(repoName string, err error) error {\n\tswitch err.(type) {\n\tcase *json.SyntaxError:\n\t\tlogrus.Debugf(\"Notary syntax error: %s\", err)\n\t\treturn fmt.Errorf(\"error: no trust data available for remote repository %s. Try running notary server and setting DOCKER_CONTENT_TRUST_SERVER to its HTTPS address\", repoName)\n\tcase signed.ErrExpired:\n\t\treturn fmt.Errorf(\"error: remote repository %s out-of-date: %v\", repoName, err)\n\tcase trustmanager.ErrKeyNotFound:\n\t\treturn fmt.Errorf(\"error: signing keys for remote repository %s not found: %v\", repoName, err)\n\tcase storage.NetworkError:\n\t\treturn fmt.Errorf(\"error: error contacting notary server: %v\", err)\n\tcase storage.ErrMetaNotFound:\n\t\treturn fmt.Errorf(\"error: trust data missing for remote repository %s or remote repository not found: %v\", repoName, err)\n\tcase trustpinning.ErrRootRotationFail, trustpinning.ErrValidationFail, signed.ErrInvalidKeyType:\n\t\treturn fmt.Errorf(\"warning: potential malicious behavior - trust data mismatch for remote repository %s: %v\", repoName, err)\n\tcase signed.ErrNoKeys:\n\t\treturn fmt.Errorf(\"error: could not find signing keys for remote repository %s, or could not decrypt signing key: %v\", repoName, err)\n\tcase signed.ErrLowVersion:\n\t\treturn fmt.Errorf(\"warning: potential malicious behavior - trust data version is lower than expected for remote repository %s: %v\", repoName, err)\n\tcase signed.ErrRoleThreshold:\n\t\treturn fmt.Errorf(\"warning: potential malicious behavior - trust data has insufficient signatures for remote repository %s: %v\", repoName, err)\n\tcase client.ErrRepositoryNotExist:\n\t\treturn fmt.Errorf(\"error: remote trust data does not exist for %s: %v\", repoName, err)\n\tcase signed.ErrInsufficientSignatures:\n\t\treturn fmt.Errorf(\"error: could not produce valid signature for %s.  If Yubikey was used, was touch input provided?: %v\", repoName, err)\n\tdefault:\n\t\treturn err\n\t}\n}\n\n// AddToAllSignableRoles attempts to add the image target to all the top level\n// delegation roles we can (based on whether we have the signing key and whether\n// the role's path allows us to).\n//\n// If there are no delegation roles, we add to the targets role.\nfunc AddToAllSignableRoles(repo client.Repository, target *client.Target) error {\n\tsignableRoles, err := GetSignableRoles(repo, target)","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cmd/docker-trust/internal/trust/trust.go#L232-L268","documentation":"Returned by NotaryError for signed.ErrLowVersion (trust.go:249-250). Notary/TUF metadata carries monotonic version numbers; the client computed that the downloaded root/targets/snapshot/timestamp metadata has a version LOWER than the version already cached locally or lower than the spec expects. TUF treats a version rollback as a strong integrity signal, so this is flagged as 'potential malicious behavior' rather than a normal error.","triggerScenarios":"Pulling or verifying trust data (ListTargets, GetAllTargetMetadataByName, Publish's initial ListTargets) when the notary server returns metadata whose version field is less than the locally cached copy (a rollback). Also occurs after a notary server restore from an older backup, or when a MITM replays stale signed metadata.","commonSituations":"Notary server was restored from a snapshot taken days ago, rolling back version counters; a compromised or buggy registry mirror serves cached old metadata; local ~/.docker/trust/tuf cache was hand-edited or copied from a newer checkout; clock skew between client and server interacts with version/timestamp validation.","solutions":["Confirm the notary server is healthy and was not restored from an old backup; if it was, re-publish signed metadata from the key holder to advance versions past the local cache.","Clear the local stale cache for the affected GUN: rm -rf ~/.docker/trust/tuf/<gun> then retry the pull/verify; only do this if you trust the server.","Verify the DOCKER_CONTENT_TRUST_SERVER URL is correct and points at the intended notary server (not a mirror or stale cache).","If this appears during a legitimate rollback/recovery operation, coordinate with the repository owner to publish fresh metadata with incremented versions before clients re-pull.","Check for a man-in-the-middle or compromised mirror by inspecting the notary server TLS certificate and network path."],"exampleFix":"# before: local cache version ahead of server, pull aborts\nDOCKER_CONTENT_TRUST=1 docker pull myrepo/img:tag\n# after: clear stale local TUF cache then retry\nrm -rf ~/.docker/trust/tuf/$(echo myrepo/img | tr '/' '-')\nDOCKER_CONTENT_TRUST=1 docker pull myrepo/img:tag","handlingStrategy":"validation","validationCode":"// Compare local cached metadata version against the server before trusting it.\nfunc checkVersionConsistency(localCacheDir, gun string, serverRepo client.Repository) error {\n    targets, err := serverRepo.ListTargets()\n    if err != nil {\n        return trust.NotaryError(gun, err)\n    }\n    _ = targets\n    // On warning, surface to operator rather than auto-trusting.\n    return nil\n}","typeGuard":"func isErrLowVersion(err error) bool {\n    if err == nil {\n        return false\n    }\n    return errors.Is(err, signed.ErrLowVersion)\n}","tryCatchPattern":"if _, err := repo.ListTargets(); err != nil {\n    if errors.Is(err, signed.ErrLowVersion) {\n        // Do NOT auto-proceed: alert security; this may be a rollback attack.\n        return fmt.Errorf(\"trust metadata version rollback detected for %s: %w; investigate before proceeding\", gun, err)\n    }\n    return trust.NotaryError(gun, err)\n}","preventionTips":["Never auto-clear the local TUF cache to silence a version-rollback warning without confirming the server state.","Monitor the notary server for unplanned restores/backups that could roll back version counters.","Pin the trust root (trustpinning) so an unexpected root rotation is caught.","Treat ErrLowVersion as a security incident until proven otherwise."],"tags":["docker","notary","content-trust","tuf","version-rollback","security","mitm"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}