apache / apache/answer

Gravatar hash is computed from the un-lowercased email, so mixed-case accounts render an identicon

オープン 初心者向け
#1,604 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Go
スター
15.7k
フォーク
1.4k
平均マージ
3日 8時間
マージ済み PR(30日)
7

説明

## Describe the bug

`pkg/gravatar.GetAvatarURL` hashes the email address without lowercasing it:

```go
// pkg/gravatar/gravatar.go
func GetAvatarURL(baseURL, email string) string {
hasher := sha256.Sum256([]byte(strings.TrimSpace(email)))
hash := hex.EncodeToString(hasher[:])
return baseURL + hash
}
```

The Gravatar specification requires the address to be trimmed **and lowercased**
before hashing, so any account whose stored address contains an uppercase letter
hashes to an address Gravatar does not know. The user's avatar is never found and
the identicon fallback (`&d=identicon`, added by the UI) is rendered instead.

Two details make this hard to work around from outside:

1. `selectedAvatar` in `internal/service/siteinfo_common/siteinfo_service.go`
recomputes the Gravatar URL from the stored address on every response, for
both `default_avatar: gravatar` and an explicit per-user `avatar.type:
gravatar`. Selecting "Gravatar" in Settings → Profile stores the correct URL
(the UI hashes correctly, see below) but the server overwrites it on read.
2. Nothing in the backend normalises a stored address. `grep -rn ToLower
internal/ | grep -i mail` returns nothing, and the external-login path copies
the provider's address verbatim
(`internal/service/user_external_login/user_external_login_service.go:258`,
`userInfo.EMail = externalUserInfo.Email`). With an OIDC/OAuth2 connector the
casing is whatever the identity provider sends, so accounts are created
mis-cased without any user or admin action.

The web UI already does this correctly, which is why the bug is easy to miss —
`ui/src/pages/Users/Settings/Profile/index.tsx`:

```ts
const str = res.e_mail.toLowerCase().trim();
const hash = sha256(str);
```

So the avatar preview in Settings → Profile shows the user's real Gravatar while
every other surface (question lists, answers, comments, user cards) shows an
identicon. Frontend and backend disagree on the hash for the same account.

## To Reproduce

1. Admin → Settings → Users: set "Default avatar" to `Gravatar`.
2. Create a user whose email address contains an uppercase letter, e.g.
`Example.User@example.com`, and register that lowercase address at
gravatar.com with an avatar image.
3. Open any page listing that user (or their profile).
4. An identicon is rendered instead of the Gravatar avatar.
5. Confirm the cause without Answer:

```console
$ printf '%s' 'example.user@example.com' | shasum -a 256 # what Gravatar expects
$ printf '%s' 'Example.User@example.com' | shasum -a 256 # what Answer sends
```

Requesting `https://www.gravatar.com/avatar/?d=404` returns 200 for the
first hash and 404 for the second.
6. Settings → Profile shows the correct avatar in its preview, because the UI
lowercases before hashing.

## Expected behavior

`GetAvatarURL` lowercases the address before hashing, matching the Gravatar
specification and the existing frontend behaviour, so a registered Gravatar is
found regardless of the casing of the stored address.

## Screenshots

n/a — the hash comparison in step 5 shows the failure directly.

## Platform

- Device: Desktop
- OS: Linux (container), macOS client
- Browser and version: Chrome (any)
- Version: v2.0.2

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

pkg/gravatar/gravatar.go の GetAvatarURL から始め、ui/src/pages/Users/Settings/Profile/index.tsx ですでに使用されている小文字化とトリミングと、入力の処理を比較します。生成された URL が正規化されたメールアドレスを使用することを確認し、大文字と小文字が混在する保存済みアドレスでも identicon fallback ではなく登録済みの Gravatar が解決されるようにします。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
go, typescript
領域
backend
issue の種類
バグ
難易度
2/5
見積もり時間
1〜3時間
活発さ
活発
明瞭さ
明確に書かれている
初心者へのやさしさ
85/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。