Skip to content

fix(weixin): check full 4-byte PNG magic signature#2970

Open
chinesepowered wants to merge 1 commit intoQwenLM:mainfrom
chinesepowered:fix/weixin-png-magic-bytes
Open

fix(weixin): check full 4-byte PNG magic signature#2970
chinesepowered wants to merge 1 commit intoQwenLM:mainfrom
chinesepowered:fix/weixin-png-magic-bytes

Conversation

@chinesepowered
Copy link
Copy Markdown
Contributor

Check full 4-byte PNG magic signature in Weixin image MIME detection.

TLDR

WeixinAdapter.detectImageMime checked only 3 of the 4 bytes of PNG's magic signature (89 50 4E 47), while the WebP branch in the same function correctly checked all 4 bytes. This is a clear oversight, not a deliberate relaxation. Extend the PNG check to include the fourth byte (0x47, 'G') for consistency.

Screenshots / Video Demo

N/A — byte-level MIME detection has no user-visible surface.

Dive Deeper

Before:

function detectImageMime(data: Buffer): string {
  if (data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e) {
    return 'image/png';   // checks only 3 of 4 signature bytes
  }
  if (data[0] === 0x47 && data[1] === 0x49 && data[2] === 0x46) {
    return 'image/gif';
  }
  if (
    data[0] === 0x52 &&
    data[1] === 0x49 &&
    data[2] === 0x46 &&
    data[3] === 0x46
  ) {
    return 'image/webp';  // WebP: full 4-byte RIFF check
  }
  return 'image/jpeg';
}

PNG's magic bytes are 89 50 4E 47. The check only validated the first three. In practice, false positives are nearly impossible — any file starting with \x89PN is essentially always PNG — but the inconsistency with the WebP branch suggests the omission was unintentional rather than a deliberate relaxation.

After:

if (
  data[0] === 0x89 &&
  data[1] === 0x50 &&
  data[2] === 0x4e &&
  data[3] === 0x47
) {
  return 'image/png';
}

Scope note: The GIF check has a similar issue (the full signature is GIF87a or GIF89a, 6 bytes) but a 3-byte GIF prefix is uniquely identifying in practice and is arguably acceptable. Left untouched to keep this PR focused.

Modified file:

  • packages/channels/weixin/src/WeixinAdapter.ts — added data[3] === 0x47 check

Reviewer Test Plan

  1. Unit-level: construct a Buffer starting with \x89\x50\x4E\x47 → should still return 'image/png'
  2. Construct a Buffer starting with \x89\x50\x4E + any other fourth byte (e.g., \x00) → now returns 'image/jpeg' (fallback); previously returned 'image/png'
  3. WebP/GIF/JPEG detection unchanged — regression check with real image buffers
  4. The function has no existing tests, so no test file changes needed

Testing Matrix

macOS Windows Linux
npm run ? pass ?
npx ? ? ?
Docker ? ? ?
Podman ? - -
Seatbelt ? - -

PNG's magic bytes are 89 50 4E 47, but detectImageMime only checked
the first three. The WebP branch in the same function correctly checks
all four bytes of its signature — the PNG path was clearly an oversight.
Extend the PNG check to include 0x47 ('G') for consistency and to
eliminate the (admittedly rare) false-positive window.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant