github ZL154/AchievementBadges_for_Jellyfin v1.7.0
v1.7.0 - Public equipped view, quest customization, full i18n, security audit

latest releases: v2.4.0, v2.3.1, v2.3.0...
5 months ago

Big feature + security release

New

  • See other users' equipped badges. Public /profiles/{userId}/equipped endpoint + coloured badge dots next to every leaderboard row, podium spot, category-leaderboard entry, and compare-view user name. Respects every privacy toggle.
  • Admin quest customization. Add / edit / override daily + weekly quests from the Jellyfin admin page. New GET/POST /admin/quests API, a quest editor section in the admin UI, and a DisabledQuestIds list for removing built-in quests your server can't satisfy.
  • Comprehensive translations. All 171 built-in badges now translated to fr / es / de / it / pt / zh-CN / ja. UI key count 553 → 614 — covers every tab (achievement profile, stats snapshot, personal records, heatmap, streak calendar, prestige leaderboard, notification prefs, server stats, compare, leaderboards, recap, quests) and the full admin page.

Fixed

  • Disable-equipped-badges toggle actually works now. The SidebarInjectionMiddleware was shipping a bloated inline script that created the sidebar pills + header dots unconditionally — ignoring both the per-user ShowEquippedShowcase preference and the admin-level ForceHideEquippedShowcase override. Middleware now emits only the three external scripts, deferring to the gated sidebar.js.
  • Live broadcast so the showcase preference takes effect without a hard refresh.

Security audit

Full audit pass. Findings applied:

HIGH

  • Compare endpoint (/compare/{userIdA}/{userIdB}) required caller to be in {userIdA, userIdB} or admin — previously any authenticated user could pollute any other user's on-disk CompareHistory. UserOwnershipFilter only guards routes with a {userId} token, which this endpoint does not use.
  • Stored XSS fixed across the admin leaderboard, audit-log viewer, and every admin-page badge renderer. Admin-authored custom badges' Title/Rarity/Description + crafted Jellyfin usernames were rendered into innerHTML unescaped. Also fixed in Pages/standalone.js showcase/equipped cards and Pages/showcase.html.

MEDIUM

  • Equipped preview in leaderboard response now hides for users with HideFromLeaderboard=true, HideFromCompare=true, or ShowEquippedShowcase=false — previously only the showcase toggle blocked it.
  • /profiles/{userId}/equipped tightened — previously required BOTH leaderboard + compare opt-outs to hide.
  • Profile-card endpoint returns a unified "unavailable" HTML page for both missing users and render failures, killing the 200 vs 404 user-enumeration oracle.
  • GiftScore now validates recipient via IUserManager, clamps amount to [1, 10000], emits an audit log, and is rate-limited. Stops an attacker from ballooning profiles JSON with bogus IDs.
  • EquipBadge, UnequipBadge, PinBadge, EquipTitle, LoginPing, BuyBadge now rate-limited with user-60-per-min.

LOW

  • Webhook HttpClient set to AllowAutoRedirect=false. WebhookUrlValidator only vets the initial URL — a malicious webhook could 302-redirect to cloud-metadata / localhost.
  • /test endpoint no longer leaks plugin version + web-injection patched paths + last-error strings to anonymous callers unless EnableDebugEndpoints is explicitly enabled (default now false).
  • Middleware exception path restores the response body more safely.

Thanks

Thanks to the French user who sent the detailed feedback on the fork (Xbox logo bug + deactivate-equipped-badges + quest modification request).


MD5: EB00EB09EAB2D172F21279035C9EDDD1

Don't miss a new AchievementBadges_for_Jellyfin release

NewReleases is sending notifications on new releases.