python / python/cpython

Email's as_bytes() method unfolds a protected header in a pgp signed message part breaking the signature.

未关闭
#153,822 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

stdlib topic-email type-bug
主要语言
Python
星标
77.2k
派生
35.9k
PR 合并指标
PR 指标待抓取

描述

Bug report

Bug description:
>>> from email import parser, policy
>>> # Create a bytes parser with default policy
>>> parser = parser.BytesParser(policy=policy.default)
>>> # Set bytes to the raw message content. Note the In-Reply-To header is folded in both the outer message
>>> # and in the proctected headers in the signed text/plain part.
>>> bytes = b"""In-Reply-To:
...  <CAMFngpXc_66qL0nUkHtT5g98BhWHPE8-KFtc6=87OvA-U7O9cw@mail.gmail.com>
... MIME-Version: 1.0
... Content-Type: multipart/signed; boundary="nextPartVzbFsyfPQFC9aKXYcHllLg";
...  micalg="pgp-sha512"; protocol="application/pgp-signature"
... 
... --nextPartVzbFsyfPQFC9aKXYcHllLg
... Content-Transfer-Encoding: 7Bit
... Content-Type: text/plain; charset="utf-8"; protected-headers="v1"
... In-Reply-To:
...  <CAMFngpXc_66qL0nUkHtT5g98BhWHPE8-KFtc6=87OvA-U7O9cw@mail.gmail.com>
... MIME-Version: 1.0
... 
... fake message here
... --nextPartVzbFsyfPQFC9aKXYcHllLg
... Content-Type: application/pgp-signature; name="signature.asc"
... Content-Description: This is a digitally signed message part.
... Content-Transfer-Encoding: 7Bit
... 
... -----BEGIN PGP SIGNATURE-----
... 
... iJEEABYKADkWIQRIePpI7xqJT+Ra2G9Prbu26Vsl/AUCalfydhsUgAAAAAAEAA5t
... YW51MiwyLjUrMS4xMiwyLDIACgkQT627tulbJfzupAD/a1gphNvf7nc+sYph/EJi
... W61+Kg356YYzRXS7SsfFI14A/2z4u28/Chqd/ETNh4VRYfl4Rf8N7eDMpFOZSEdM
... bTkF
... =QWJd
... -----END PGP SIGNATURE-----
... 
... --nextPartVzbFsyfPQFC9aKXYcHllLg--
... """
>>> # Create a message object.
>>> msg = parser.parsebytes(bytes)
>>> # and print its as_bytes() representation.
>>> print(msg.as_bytes().decode())
In-Reply-To:
 <CAMFngpXc_66qL0nUkHtT5g98BhWHPE8-KFtc6=87OvA-U7O9cw@mail.gmail.com>
MIME-Version: 1.0
Content-Type: multipart/signed; boundary="nextPartVzbFsyfPQFC9aKXYcHllLg";
 micalg="pgp-sha512"; protocol="application/pgp-signature"

--nextPartVzbFsyfPQFC9aKXYcHllLg
Content-Transfer-Encoding: 7Bit
Content-Type: text/plain; charset="utf-8"; protected-headers="v1"
In-Reply-To: <CAMFngpXc_66qL0nUkHtT5g98BhWHPE8-KFtc6=87OvA-U7O9cw@mail.gmail.com>
MIME-Version: 1.0

fake message here
--nextPartVzbFsyfPQFC9aKXYcHllLg
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: This is a digitally signed message part.
Content-Transfer-Encoding: 7Bit

-----BEGIN PGP SIGNATURE-----

iJEEABYKADkWIQRIePpI7xqJT+Ra2G9Prbu26Vsl/AUCalfydhsUgAAAAAAEAA5t
YW51MiwyLjUrMS4xMiwyLDIACgkQT627tulbJfzupAD/a1gphNvf7nc+sYph/EJi
W61+Kg356YYzRXS7SsfFI14A/2z4u28/Chqd/ETNh4VRYfl4Rf8N7eDMpFOZSEdM
bTkF
=QWJd
-----END PGP SIGNATURE-----

--nextPartVzbFsyfPQFC9aKXYcHllLg--

>>> # Note that the protected In-Reply-To header in the signed text/plain part is unfolded even though it is
>>> # 81 bytes long.
>>> # Now get only the text/plain part.
>>> part = msg.get_payload(0)
>>> # And see it as_bytes().
>>> print(part.as_bytes().decode())
Content-Transfer-Encoding: 7Bit
Content-Type: text/plain; charset="utf-8"; protected-headers="v1"
In-Reply-To:
 <CAMFngpXc_66qL0nUkHtT5g98BhWHPE8-KFtc6=87OvA-U7O9cw@mail.gmail.com>
MIME-Version: 1.0

fake message here
>>> # And here the header is properly folded.

The problem here is if a message of which the above is an excerpt is received by some application, e.g. Mailman, and later resent to recipients by passing the message object to Python's smtplib.SMTP.send_message() method which serializes the message with the as_bytes() method applied to the whole message, the resent message has the unfolded protected In-Reply-To header in the signed part breaking the signature.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Linked PRs
  • gh-154107

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

先复现报告中的 BytesParser 和 Message.as_bytes(),然后跟踪通过 smtplib.SMTP.send_message() 进行的序列化。验证 multipart/signed 消息序列化时,受保护的 In-Reply-To 标头仍保持折叠状态,以免原始签名失效。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
backend
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
30/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。