gravitational/teleport · error

A trusted device is required to access this resource but thi

Error message

A trusted device is required to access this resource but this device has not been registered as a trusted device; use 'tsh device enroll' to register as a trusted device.

See https://goteleport.com/docs/zero-trust-access/device-trust/device-management/#troubleshooting for help.

What it means

Error "A trusted device is required to access this resource but this device has not been registered as a trusted device; use 'tsh device enroll' to register as a trusted device. See https://goteleport.com/docs/zero-trust-access/device-trust/device-management/#troubleshooting for help. " thrown in gravitational/teleport.

Source

Thrown at lib/srv/app/connections_handler.go:933

func writeTrustedDeviceRequired(w http.ResponseWriter, r *http.Request, code int) {
	if isBrowserUserAgent(r.UserAgent()) {
		const body = `<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>Trusted device required</title></head>
<body>
<p>A trusted device is required to access this resource, but this session has not been authorized with Device Trust. Follow <a href="` + trustedDeviceRequiredWebUIDocsURL + `" target="_blank">the Web UI troubleshooting guide</a> to authorize the session with Device Trust.</p>
<p>If accessing the resource through VNet or a local proxy, make sure the device running Teleport Connect or tsh is registered and enrolled. See <a href="` + trustedDeviceRequiredAppAccessDocsURL + `" target="_blank">the app access troubleshooting guide</a> for help.</p>
</body>
</html>
`
		w.Header().Set("Content-Type", "text/html; charset=utf-8")
		w.Header().Set("X-Content-Type-Options", "nosniff")
		w.WriteHeader(code)
		_, _ = w.Write([]byte(body))
		return
	}

	http.Error(w, `A trusted device is required to access this resource but this device has not been registered as a trusted device; use 'tsh device enroll' to register as a trusted device.

See `+trustedDeviceRequiredDocsURL+` for help.
`, code)
}

// isBrowserUserAgent reports whether ua plausibly comes from a web browser, as
// opposed to a CLI (tsh, curl) or some SDK client. It relies on the historical
// quirk that essentially every browser UA begins with "Mozilla/" and contains
// a known engine token. Modern browsers (Chrome, Safari, Edge, Opera, mobile
// browsers) are all WebKit- or Blink-based and carry "AppleWebKit"; the Firefox
// family carries "Gecko/".
func isBrowserUserAgent(ua string) bool {
	lower := strings.ToLower(ua)
	return strings.HasPrefix(lower, "mozilla/") &&
		(strings.Contains(lower, "applewebkit") || strings.Contains(lower, "gecko/"))
}

// getConnectionInfo extracts identity information from the provided

View on GitHub (pinned to 1283425b60)

Solutions

  1. Enroll the device: run 'tsh device enroll' with an enrollment token from an administrator
  2. If accessing via VNet or a local proxy, ensure it is launched from the enrolled device and the device certificate is present
  3. See the Device Trust troubleshooting docs linked in the error message
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at lib/srv/app/connections_handler.go:933 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/8cf88d12122dd439. Report an issue: GitHub.