fix(wecom): support pic_url and fix AES key base64 padding for image … - #12390
fix(wecom): support pic_url and fix AES key base64 padding for image …#12390zogwei wants to merge 1 commit into
Conversation
…decryption WeCom AI Bot sends image URLs in the `pic_url` field (not `url`). Additionally, the `aeskey` is 43-character base64 without standard padding, causing base64.b64decode() to raise Incorrect padding. Changes: - Recognize `pic_url` in inbound media references - Add `_decode_wecom_aes_key()` to handle unpadded base64 - Use the new decoder in `_decrypt_file_bytes()` - Add `_try_decrypt_variants()` as fallback for different AES modes
teknium1
left a comment
There was a problem hiding this comment.
Thanks for investigating WeCom AI Bot image delivery. The unpadded-Base64 part is already present on current main: plugins/platforms/wecom/adapter.py:1069-1073 pads before decoding (commit 8f4c0bf0882c3c7258a65e3adade12d5b08068ea).
Problems
gateway/platforms/wecom.py:748adds apic_urlfallback only after a media reference exists._extract_media()still only forwards nestedimagedictionaries (plugins/platforms/wecom/adapter.py:719-723), so a top-level AI Botpic_urlnever reaches this code.- The proposed variant fallback accepts any non-
Nonecandidate atgateway/platforms/wecom.py:770; its scorer can retain a score-zero plaintext. There is no regression coverage for rejecting incorrectly decrypted data. - The PR changes only the former inline adapter and no tests. Current main moved the live implementation to
plugins/platforms/wecom/adapter.pyin5600105478ffde29d7566b45421b100eaa29c4ef.
Suggested changes
- Port a focused top-level
pic_urlextraction path to the bundled adapter and add tests intests/gateway/test_wecom.pycovering URL/key propagation and decrypt/cache behavior. - Reuse current padding logic; limit any additional key-format handling to documented formats with deterministic validation rather than AES-mode guessing.
Automated hermes-sweeper review.
| return cache_document_from_bytes(raw, filename), mimetypes.guess_type(filename)[0] or "application/octet-stream" | ||
|
|
||
| url = str(media.get("url") or "").strip() | ||
| url = str(media.get("url") or media.get("pic_url") or "").strip() |
There was a problem hiding this comment.
This fallback only helps if _extract_media() has already passed a media dictionary to _cache_media(). The PR does not add a reference for a top-level AI Bot pic_url, so that reported payload shape still never reaches this line. Construct the image reference in _extract_media() and cover it with a regression test.
| if decrypted is None: | ||
| decrypted = self._try_decrypt_variants(raw, aes_key, kind) | ||
|
|
||
| if decrypted is not None: |
There was a problem hiding this comment.
_try_decrypt_variants() can return its first score-zero candidate, so this accepts plaintext that was not positively validated. Avoid heuristic AES-mode fallback or require a deterministic format/padding validation before caching the result.
…decryption
WeCom AI Bot sends image URLs in the
pic_urlfield (noturl). Additionally, theaeskeyis 43-character base64 without standard padding, causing base64.b64decode() to raise Incorrect padding.Changes:
pic_urlin inbound media references_decode_wecom_aes_key()to handle unpadded base64_decrypt_file_bytes()_try_decrypt_variants()as fallback for different AES modesWhat does this PR do?
Related Issue
Fixes #
Type of Change
Changes Made
How to Test
Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AFor New Skills
hermes --toolsets skills -q "Use the X skill to do Y"Screenshots / Logs