[PM-36584] Bidirectional C2 in icons.bitwarden.net#7668
Conversation
🤖 Bitwarden Claude Code ReviewOverall Assessment: REQUEST CHANGES This PR adds PNG chunk allowlisting and ICO-embedded PNG stripping to Code Review Details
|
| if (length < 0 || (long)offset + 12 + length > bytes.Length) | ||
| { | ||
| return bytes; | ||
| } |
There was a problem hiding this comment.
Details and fix
When a chunk has length < 0 or a length that overflows the buffer, StripPngMetadata returns the original bytes array unmodified. An attacker controlling the icon source can intentionally craft a PNG that places a malicious chunk (e.g. tEXt carrying C2 payload) early in the stream, followed by a chunk with a deliberately invalid length. The parser hits this branch, bails, and the full original byte array — including the malicious chunk — is delivered to the client.
This directly undermines the PR's stated goal of dropping anything "an attacker might try." Since the threat model assumes the upstream server is hostile, a malformed PNG should be treated as untrusted, not preserved.
The same fail-open pattern appears in StripIcoEmbeddedPngMetadata at the early-return branches for invalid count, entry size, and data offset.
Suggested fix: on parse failure, return the bytes already written to output plus a synthetic IEND (or return an empty array and let the caller drop the icon), so malformed input fails closed rather than open.
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #7668 +/- ##
==========================================
+ Coverage 59.98% 60.00% +0.02%
==========================================
Files 2133 2133
Lines 93731 93815 +84
Branches 8311 8325 +14
==========================================
+ Hits 56220 56296 +76
- Misses 35531 35535 +4
- Partials 1980 1984 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|



🎟️ Tracking
jira
📔 Objective
strip PNG metadata chunks
In IconLink.cs, FetchAsync just returns the raw bytes. Before we hand them back, we should walk the PNG chunk list and only keep the ones we actually need for rendering:
Keep: IHDR, PLTE, IDAT, IEND, tRNS, sRGB, gAMA, cHRM
Drop everything else. That kills tEXt/iTXt/zTXt and anything else an attacker might try. PNG chunk structure is simple (4-byte length, 4-byte type, data, CRC). Apply the same logic to PNG frames embedded inside ICO files.
Also drop SVG support from the proxy