RocketChat/Rocket.Chat · warning

The server detected an unauthenticated access to an user ava

Error message

The server detected an unauthenticated access to an user avatar. This type of request will soon be blocked by default.

What it means

Logged (throttled to once per 30 minutes) by userCanAccessAvatar in apps/meteor/server/routes/avatar/utils.ts. When the setting Accounts_AvatarBlockUnauthenticatedAccess is enabled, every avatar request is authenticated via rc_uid + rc_token (headers or query) checked against Users.findOneByIdAndLoginToken(hashLoginToken(rc_token)). If the credentials are absent or invalid, this warning fires — it announces that unauthenticated avatar access, historically allowed, will be blocked by default in a future version.

Source

Thrown at apps/meteor/server/routes/avatar/utils.ts:110

async function isUserAuthenticated({ headers, query }: Pick<IIncomingMessage, 'headers' | 'query'>) {
	let { rc_uid, rc_token } = query;

	if (!rc_uid && headers.cookie) {
		rc_uid = cookie.get('rc_uid', headers.cookie);
		rc_token = cookie.get('rc_token', headers.cookie);
	}

	if (rc_uid == null || rc_token == null) {
		return false;
	}

	const userFound = await Users.findOneByIdAndLoginToken(rc_uid, hashLoginToken(rc_token), { projection: { _id: 1 } }); // TODO memoize find

	return !!userFound;
}

const warnUnauthenticatedAccess = throttle(() => {
	console.warn('The server detected an unauthenticated access to an user avatar. This type of request will soon be blocked by default.');
}, 60000 * 30); // 30 minutes

export async function userCanAccessAvatar({ headers = {}, query = {} }: IIncomingMessage) {
	if (!settings.get('Accounts_AvatarBlockUnauthenticatedAccess')) {
		return true;
	}

	const isAuthenticated = await isUserAuthenticated({ headers, query });
	if (!isAuthenticated) {
		warnUnauthenticatedAccess();
	}

	return isAuthenticated;
}

const getFirstLetter = (name: string) => {
	const sanitizedName = sanitizeHtml(name);
	return sanitizedName.substring(0, 1).toUpperCase();

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Identify the referrers hitting /avatar/* without credentials (access logs) — usually email templates, external sites, or integrations.
  2. Serve avatars to logged-in clients only: use the authenticated browser session (cookies) or append valid rc_uid + rc_token query params for machine access.
  3. For emails/external embeds, stop inlining the server avatar URL; use the recipient-side rendered avatar or a public CDN asset instead.
  4. If anonymous access is an intentional product requirement for your deployment, keep Accounts_AvatarBlockUnauthenticatedAccess = false and document the future behavior change.

Example fix

// before: anonymous embed that triggers the warning once the setting is on
<img src="https://chat.example.com/avatar/john.doe" />

// after: authenticated request with token pair
const url = `https://chat.example.com/avatar/john.doe?rc_uid=${userId}&rc_token=${authToken}`;
// (fetch token via REST login: POST /api/v1/login)
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: verify credentials exist before requesting a blocked avatar
const canFetchAvatar = (userId: string | null, token: string | null): boolean =>
  userId != null && token != null;

const url = canFetchAvatar(Meteor.userId(), Meteor._localStorage.getItem('Meteor.loginToken'))
  ? `/avatar/${username}?rc_uid=${Meteor.userId()}&rc_token=${token}`
  : null; // fall back to a local placeholder instead of an anonymous request

Prevention

When it happens

Trigger: A request to /avatar/<username> (or /avatar/<username>.jpg) arrives with Accounts_AvatarBlockUnauthenticatedAccess = true, and the request carries no rc_uid/rc_token pair, or the token does not hash-match a stored login token for that user. Frequent producers: <img src="/avatar/..."> embedded in emails, external websites, or chat previews; proxies that strip cookies; scrapers and monitoring tools hitting avatar URLs; logged-out pages hotlinking avatars.

Common situations: Administrators enabling Accounts_AvatarBlockUnauthenticatedAccess ahead of the default flip; webhook/notification emails that inline avatar URLs without auth tokens; migrating public workspaces to private ones; CDN caching of avatar URLs that were fetched anonymously. Once the setting blocks, those images return 401/403 instead of rendering.

Understand the failure class

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/a29f5b50ea7f8431. Report an issue: GitHub.