Skip to content

fix(wecom): correct image extension detection and handle URL-encoded aeskey #10085

@zhoujian78

Description

@zhoujian78

Bug Description

When receiving images via WeCom, the cached image files have .bin extension instead of the correct .jpg/.png extension.

Root Cause

Two issues in gateway/platforms/wecom.py:

1. Image extension detection returns .bin

WeCom CDN returns content-type: application/octet-stream for images. mimetypes.guess_extension("application/octet-stream") returns .bin. Since .bin is a truthy value, the code short-circuits and returns .bin directly, never reaching the _detect_image_ext() magic-byte fallback.

Fix: Skip .bin in _guess_extension() so it falls through to real format detection.

# Before
if ext:
    return ext

# After
if ext and ext != ".bin":
    return ext

2. AES key URL encoding and base64 padding

The aeskey parameter in WeCom image URLs is sometimes URL-encoded (e.g. %2F instead of /, %3D instead of =), and may be missing base64 padding. This causes base64.b64decode() to fail, making all images return None from _cache_media().

Fix: URL-decode the key and add padding before decoding.

# Before
aes_key = str(media.get("aeskey") or "").strip()
if aes_key:
    try:
        raw = self._decrypt_file_bytes(raw, aes_key)
    except Exception as exc:
        logger.debug("[%s] Failed to decrypt %s from %s: %s", self.name, kind, url, exc)
        return None

# After
aes_key = str(media.get("aeskey") or "").strip()
if aes_key:
    from urllib.parse import unquote
    aes_key = unquote(aes_key)
    aes_key = aes_key + "=" * ((4 - len(aes_key) % 4) % 4)
    try:
        raw = self._decrypt_file_bytes(raw, aes_key)
    except Exception as exc:
        logger.info("[WeCom DEBUG] Failed to decrypt %s from %s (aeskey=%s): %s", kind, url, aes_key, exc)
        return None

Verification

After the fix, images are correctly saved with proper extensions:

  • img_d3ff59c13352.jpg (magic bytes ffd8ff = JPEG)
  • img_xxxxxxxxxxxx.png (magic bytes 89504e47 = PNG)

Files Changed

  • gateway/platforms/wecom.py: 2 fixes in _guess_extension() and _cache_media()

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsplatform/wecomWeCom / WeChat Work adaptertype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions