Bad MD5 filename for non-default avatars #10312

Closed
opened 2025-11-02 09:03:54 -06:00 by GiteaMirror · 6 comments
Owner

Originally created by @astos-marcb on GitHub (Feb 21, 2023).

Originally assigned to: @Zettat123 on GitHub.

Description

The avatar picture endpoint always returns the default picture.
See difference to actual profile picture for account

Path for the non-default picture resolves to the file content hash md5(<id>-<md5(content)>) (as saved in u.Avatar) instead of the standardized md5(email).

Gitea Version

1.18.4

Can you reproduce the bug on the Gitea demo site?

Yes

Log Gist

No response

Screenshots

No response

Git Version

2.36.5

Operating System

Alpine Linux

How are you running Gitea?

docker, verified on https://try.gitea.io/

Database

SQLite

Originally created by @astos-marcb on GitHub (Feb 21, 2023). Originally assigned to: @Zettat123 on GitHub. ### Description The avatar picture [endpoint](https://try.gitea.io/avatars/5b3f1f53451d50511958a1292e0bb0ce) always returns the `default` picture. See difference to actual profile picture for [account](https://try.gitea.io/astos-marcb) Path for the `non-default` picture [resolves](https://github.com/go-gitea/gitea/blob/bd820aa9c52da4568b460a0b8604287f8ed8df26/models/user/avatar.go#L25) to the file content hash `md5(<id>-<md5(content)>)` (as saved in u.Avatar) instead of the standardized `md5(email)`. ### Gitea Version 1.18.4 ### Can you reproduce the bug on the Gitea demo site? Yes ### Log Gist _No response_ ### Screenshots _No response_ ### Git Version 2.36.5 ### Operating System Alpine Linux ### How are you running Gitea? docker, verified on https://try.gitea.io/ ### Database SQLite
GiteaMirror added the type/bug label 2025-11-02 09:03:54 -06:00
Author
Owner

@Zettat123 commented on GitHub (Feb 22, 2023):

Maybe you want to get your custom avatar by accessing /avatars/{hash} and the hash is md5(email)?
Actually the hash filename only indicates a file, not a user.

@Zettat123 commented on GitHub (Feb 22, 2023): Maybe you want to get your **custom avatar** by accessing `/avatars/{hash}` and the `hash` is `md5(email)`? Actually the hash filename only indicates a file, not a user.
Author
Owner

@astos-marcb commented on GitHub (Feb 22, 2023):

Exactly, the current user avatar should always be available at /avatars/{md5(email)} (standardized endpoint for avatars).

The default avatar is saved to the correct file name, a custom avatar is not.
Instead, a user+content-derived hash is used as the filename (value in User.Avatar) instead of md5(email).

Setting the default avatar will actually change the value in User.Avatar to md5(email), which in turn does not conform to the expected value in other parts of the code (detecting re-upload of same picture for a user).

An easy fix in CustomAvatarRelativePath would be to just throw away what's saved in User.Avatar (the user/content-derived MD5 sum in case of custom avatar) and just always use the correct filename conforming to avatars.HashEmail(User.Email).

This will of course break references to existing custom avatars which are already saved to a misnamed files…

@astos-marcb commented on GitHub (Feb 22, 2023): Exactly, the current user avatar should *always* be available at `/avatars/{md5(email)}` (standardized endpoint for avatars). The default avatar is saved to the *correct* file name, a **custom avatar** is **not**. Instead, a user+content-derived hash is used as the filename (value in `User.Avatar`) instead of `md5(email)`. Setting the **default avatar** will actually change the value in `User.Avatar` to `md5(email)`, which in turn does not conform to the expected value in other parts of the code (detecting re-upload of same picture for a user). An easy fix in *CustomAvatarRelativePath* would be to just throw away what's saved in `User.Avatar` (the user/content-derived MD5 sum in case of **custom avatar**) and just always use the correct filename conforming to `avatars.HashEmail(User.Email)`. This will of course break references to existing custom avatars which are already saved to a misnamed files…
Author
Owner

@Zettat123 commented on GitHub (Feb 23, 2023):

Gitea's avatar service is not de designed to be a service like Gravatar. The hash filename only used to distinguish between different files.
Sorry I couldn't help more because we have no plans to develop this feature in the short term. Please feel free to reopen this issue if you still need help.

@Zettat123 commented on GitHub (Feb 23, 2023): Gitea's avatar service is not de designed to be a service like Gravatar. The hash filename only used to distinguish between different files. Sorry I couldn't help more because we have no plans to develop this feature in the short term. Please feel free to reopen this issue if you still need help.
Author
Owner

@zeripath commented on GitHub (Mar 4, 2023):

It's a fairly interesting idea for Gitea to implement/replicate Gravatar's funcitonality and I don't believe that it would be too difficult to do this - but yes I don't believe that it is a bug that Gitea does not implement this.

@astos-marcb you could open a feature request but you'd need to link to the specs for it.

@zeripath commented on GitHub (Mar 4, 2023): It's a fairly interesting idea for Gitea to implement/replicate Gravatar's funcitonality and I don't believe that it would be too difficult to do this - but yes I don't believe that it is a bug that Gitea does not implement this. @astos-marcb you could open a feature request but you'd need to link to the specs for it.
Author
Owner

@astos-marcb commented on GitHub (Mar 9, 2023):

In a way Gitea does already implement/provide it (supply an avatar picture at URL /avatars/{md5(email)})
The problem is that default (generated) and custom (uploaded) avatars are not named and treated equally (endpoint always resolves to the default avatar file).

A quick-and-dirty and incomplete solution would be to forgo content checking and always save the avatar file as avatars/{md5(mail)}.
This would not solve the conflicting naming conventions for user avatar and repo avatar and has no chance of supporting multiple mail addresses for the same user.

Ideally, logic used for repository avatar filenames ({repo-id}-{upload-checksum}) should be used and a correct mapping from all email entries of a user should be done in the router layer.
The default (out of the box) behavior of creating the default file with a different name would not have any drawbacks (assuming the router part is working as described).

A possible middle ground (and easy to debug solution) would employ:

  • use same naming convention as for repos for the avatar file ({user-id}-{upload-checksum})
  • create symbolic md5(email) links for all mail entries for a user (guaranteed to be unique per instance).

For migrating user-supplied avatars the transformed name can be just {user-id}-<zeros> to indicate unknown/discarded content checksum (it currently gets rehashed with the user mail address).

@astos-marcb commented on GitHub (Mar 9, 2023): In a way Gitea _does_ already implement/provide it (supply an avatar picture at URL `/avatars/{md5(email)}`) The problem is that default (generated) and custom (uploaded) avatars are not named and treated equally (endpoint always resolves to the default avatar file). A quick-and-dirty and **incomplete** solution would be to forgo content checking and always save the avatar file as `avatars/{md5(mail)}`. This would **not** solve the conflicting naming conventions for `user` avatar and `repo` avatar **and** has no chance of supporting multiple mail addresses for the same user. Ideally, logic used for repository avatar filenames (`{repo-id}-{upload-checksum}`) should be used and a correct mapping from *all* email entries of a user should be done in the router layer. The default (out of the box) behavior of creating the default file with a different name would not have any drawbacks (assuming the router part is working as described). A possible middle ground (and easy to debug solution) would employ: - use same naming convention as for repos for the avatar file (`{user-id}-{upload-checksum}`) - create symbolic `md5(email)` links for **all** mail entries for a user (guaranteed to be unique per instance). For migrating user-supplied avatars the *transformed* name can be just `{user-id}-<zeros>` to indicate unknown/discarded content checksum (it currently gets rehashed with the user mail address).
Author
Owner

@astos-marcb commented on GitHub (Mar 9, 2023):

Hm, there are already done some changes to unify avatar naming for v1.20.
Will have a look how/if this affects current /avatars/{md5(email)} behavior (break/improve?).
UNAFFECTED: The filename for generated avatars (still) uses md5({email}) instead of new/unified sha256({user}-{data}).

@astos-marcb commented on GitHub (Mar 9, 2023): Hm, there are already done some changes to unify avatar naming for [`v1.20`](https://github.com/go-gitea/gitea/pull/22289). Will have a look how/if this affects current `/avatars/{md5(email)}` behavior (break/improve?). _UNAFFECTED_: The filename for generated avatars (still) uses `md5({email})` instead of new/unified `sha256({user}-{data})`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#10312