• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

go-pkgz / auth / 26198058385
85%

Build:
DEFAULT BRANCH: master
Ran 21 May 2026 12:32AM UTC
Jobs 1
Files 25
Run time 1min
Badge
Embed ▾
README BADGES
x

If you need to use a raster PNG badge, change the '.svg' to '.png' in the link

Markdown

Textile

RDoc

HTML

Rst

21 May 2026 12:29AM UTC coverage: 85.395% (+0.1%) from 85.291%
26198058385

push

github

web-flow
fix(avatar): prevent stored XSS via content-type spoofing (#290)

* fix(avatar): reject non-image content to prevent stored XSS via content-type spoofing

The avatar proxy stored whatever bytes upstream returned at u.Picture and served
them back with whatever http.DetectContentType decided — including text/html for
HTML/script payloads. A user whose login flow allows attacker-controlled u.Picture
(custom OAuth provider, self-signup with picture URL) could plant HTML in the avatar
store and have it served from the auth-service origin as text/html, executing JS in
that origin.

Layered defense:

  * Proxy.resize() validates input via image.DecodeConfig (cheap, no pixel
    allocation) before any image.Decode. Refuses non-image content with nil so
    attacker payloads (HTML / SVG / text) never reach Store.Put. Previously it
    silently fell back to teeBuf on decode failure, poisoning the store.
  * Per-pixel cap maxAvatarPixels (16 MP) rejects compressed decompression-bomb
    images that would force image.Decode to allocate gigabytes of raster memory
    on a single login attempt. Multiplication uses int64 to avoid wraparound on
    32-bit builds (GOARCH=386, 32-bit arm) where the int32 product of 16-bit GIF
    or JPEG dimensions would otherwise bypass the cap.
  * The no-resize path (limit<=0 or image already fits) returns the original
    bytes verbatim so animated GIFs and other multi-frame formats round-trip
    without being flattened to the first frame.
  * Proxy.Put() falls back to a generated identicon when resize() returns nil.
  * Proxy.PutContent() returns an explicit error for non-image input.
  * Proxy.Handler() validates served bytes via the new safeImgContentType helper
    (strict allowlist: image/{png,jpeg,gif,webp,bmp,x-icon}; image/svg+xml is
    explicitly rejected because SVG can execute scripts when navigated to top
    level). This catches stores poisoned before this fix and any future
    regression at serve time.
  * Every Ha... (continued)

96 of 105 new or added lines in 2 files covered. (91.43%)

2 existing lines in 1 file now uncovered.

3017 of 3533 relevant lines covered (85.39%)

8.19 hits per line

Uncovered Changes

Lines Coverage ∆ File
9
82.45
2.24% avatar/avatar.go

Coverage Regressions

Lines Coverage ∆ File
2
82.45
2.24% avatar/avatar.go
Jobs
ID Job ID Ran Files Coverage
1 26198058385.1 21 May 2026 12:32AM UTC 25
85.39
GitHub Action Run
Source Files on build 26198058385
  • Tree
  • List 25
  • Changed 2
  • Source Changed 0
  • Coverage Changed 2
Coverage ∆ File Lines Relevant Covered Missed Hits/Line
  • Back to Repo
  • b19c8d77 on github
  • Prev Build on refs/tags/v2.1.3 (#25620390172)
  • Next Build on master (#26203178077)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc