Skip to content

Expose Expat XML attack protection APIs #90949

Closed

Description

@gpshead
BPO 46793
Nosy @gpshead, @hartwork, @corona10

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2022-02-18.21:27:31.809>
labels = ['type-feature', '3.11']
title = 'expose expat XML billion laughs attack mitigation APIs'
updated_at = <Date 2022-02-25.02:16:52.654>
user = 'https://github.com/gpshead'

bugs.python.org fields:

activity = <Date 2022-02-25.02:16:52.654>
actor = 'sping'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = []
creation = <Date 2022-02-18.21:27:31.809>
creator = 'gregory.p.smith'
dependencies = []
files = []
hgrepos = []
issue_num = 46793
keywords = []
message_count = 2.0
messages = ['413513', '413955']
nosy_count = 3.0
nosy_names = ['gregory.p.smith', 'sping', 'corona10']
pr_nums = []
priority = 'normal'
resolution = None
stage = 'needs patch'
status = 'open'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue46793'
versions = ['Python 3.11']

Linked PRs

Activity

  1. hartwork commented on Sep 17, 2025

    @hartwork
    Contributor

    By orphan I meant without a parent parser.

    @picnixz oh I see!

    Considering the failure can only happen when either the parser has a parent or the factor is invalid as a number, I'm going to simply remake those checks on Python's side so that I can raise appropriate exceptions (ideally I would have loved having a return code being returned by expat so that I know what exactly happened but it's also fine).

    I'm reading that as doing a value range check in CPython "manually" — 1.0 to +infinity (both inclusive) for amplification and 0 to 2^64-1 (both inclusive) for the threshold — and treating failure to set after passed input validation as "must have failed because there was a parent parser present". Is that what you had in mind?

    I could introduce a new API function XML_Parser XML_ParserGetParent(XML_Parser parser) just for this for Expat 2.7.3 (and aim at getting it released before — say — 2025-10-20), if it changes the picture for CPython significantly, what do you think?

  2. picnixz commented on Sep 17, 2025

    @picnixz
    Member

    I'm reading that as doing a value range check in CPython "manually" 

    Yes.

    I would like to return a meaningful error when someone uses an invalid factor so that users know that it was the factor that was wrong and I also want to have a meaningful error when users use the function for parsers with a parent.

    Ideally I would like the functions to return an error code if they failed (instead of XML_FALSE) and that error code should be different depending on the error that happened (so that I can distinguish between a "bad" parser and a "bad" factor).

    I don't want to burden Expat with utility functions only for us, so I also don't mind raising a generic error and document what could be the reason.

  3. hartwork commented on Sep 17, 2025

    @hartwork
    Contributor

    @picnixz okay 👍

  4. added 3 commits that reference this issue on Sep 26, 2025
  5. changed the title [-]expose expat XML billion laughs attack mitigation APIs[/-] [+]Expose Expat XML attack mitigation APIs[/+] on Sep 26, 2025
  6. added 3 commits that reference this issue on Sep 26, 2025
  7. added a commit that references this issue on Sep 26, 2025
  8. changed the title [-]Expose Expat XML attack mitigation APIs[/-] [+]Expose Expat XML attack protection APIs[/+] on Sep 27, 2025
  9. added 2 commits that reference this issue on Sep 28, 2025
  10. added 6 commits that reference this issue on Oct 2, 2025
  11. added a commit that references this issue on Oct 4, 2025
  12. added a commit that references this issue on Oct 7, 2025
  13. picnixz commented on Oct 8, 2025

    @picnixz
    Member

    Ok, so here's the plan for the future.

    1. We have PRs for tuning the allocation limiter in pyexpat for 3.10 up to 3.14. main already has the feature. @hartwork, could you go through the PRs and update them accordingly? TiA.
    2. Next, we should create backports for tuning the billion laughs protection in pyexpat for 3.10 up to 3.14. main already has the feature. For that, I'm going to handle the backports after the PRs above are done.
    3. Finally, we should design an API for tuning those protections from etree parsers as it was done for .flush(). I don't know if we need to do it for SAX parsers though as I now don't remember if parser deferral couold be tuned on SAX parsers (maybe it can because of inheriting interfaces).

    What I want is that, at any point of the time, security branches and release branches have the same APIs. As discused, 3.9 won't have those APIs and will live with the defaults. I don't know when 3.10/3.11 (@pablogsal) and 3.12 (@Yhg1s) will have their security releases but if it's in the next days, I'm going to skip those releases and wait for the next one. Then we can merge the first batch of PRs (or we can already do so if (1) is ready). Then, we merge (2) but only if we are able to make it before (it depends on when (1) is done). Note that I'll be unavailable next week so if there is a release planned for the next 10 days, I would prefer skipping the introduction of those APIs and add them in the one after. In the meantime, we can work on (3) so that we have something to put in main.

  14. hartwork commented on Oct 8, 2025

    @hartwork
    Contributor

    Ok, so here's the plan for the future.

    1. We have PRs for tuning the allocation limiter in pyexpat for 3.10 up to 3.14. main already has the feature. @hartwork, could you go through the PRs and update them accordingly? TiA.

    @picnixz they are all ready to review (and merge) as far as I am concerned. Previous workarounds for issue #139400 have been been dropped from all of them.

    1. Next, we should create backports for tuning the billion laughs protection in pyexpat for 3.10 up to 3.14. main already has the feature. For that, I'm going to handle the backports after the PRs above are done.

    Yes.

    1. Finally, we should design an API for tuning those protections from etree parsers as it was done for .flush(). I don't know if we need to do it for SAX parsers though as I now don't remember if parser deferral couold be tuned on SAX parsers (maybe it can because of inheriting interfaces).

    Yes.

    What I want is that, at any point of the time, security branches and release branches have the same APIs. As discused, 3.9 won't have those APIs and will live with the defaults. I don't know when 3.10/3.11 (@pablogsal) and 3.12 (@Yhg1s) will have their security releases but if it's in the next days, I'm going to skip those releases and wait for the next one. Then we can merge the first batch of PRs (or we can already do so if (1) is ready). Then, we merge (2) but only if we are able to make it before (it depends on when (1) is done). Note that I'll be unavailable next week so if there is a release planned for the next 10 days, I would prefer skipping the introduction of those APIs and add them in the one after. In the meantime, we can work on (3) so that we have something to put in main.

    The new API was made with hasattr in mind, so I personally do not see value in synchronisation across backports. What is the value bought by these costs?

  15. picnixz commented on Oct 8, 2025

    @picnixz
    Member

    I agree that with hasattr checks we won't need to bother, but it's more for syncing on our side. But we can also try to avoid this. Now, however, I wonder whether we should also not indicate hasattr checks for the new Expat interface in the docs. Because, while we released 3.14.0, the new methods will only be present in 3.14.1, so we should also indicate this in the docs. What do you think?

  16. hartwork commented on Oct 8, 2025

    @hartwork
    Contributor

    Now, however, I wonder whether we should also not indicate hasattr checks for the new Expat interface in the docs.

    @picnixz is the "not" by accident here ⬆️ and you meant to say the opposite?

    Because, while we released 3.14.0, the new methods will only be present in 3.14.1, so we should also indicate this in the docs. What do you think?

    Do we have any places mis-indicating they would have arrived in 3.14.0? I'm not aware of any but if we have some, let's make those say 3.14.1 and backports, yes. Past PR #116278 is related.

  17. picnixz commented on Oct 8, 2025

    @picnixz
    Member

    is the "not" by accident here ⬆️ and you meant to say the opposite?

    Yes my bad. I meant "we should add this".

    Do we have any places mis-indicating they would have arrived in 3.14.0?

    I don't think so. Strictly speaking, with .. versionadded:: next, we should be fine because it will be marked ("added in version 3.14.1") in the online docs. But to stress this, it would be good if the attack section (of pyexpat) mentions the "hasattr" trick.

  18. hartwork commented on Oct 8, 2025

    @hartwork
    Contributor

    I meant "we should add this".

    @picnixz alright 👍

    But to stress this, it would be good if the attack section (of pyexpat) mentions the "hasattr" trick.

    @picnixz the attack section will probably be overlooked by someone just reading the docs of the four specific founctions, so I would personally want to copy the approach from https://github.com/python/cpython/pull/116278/files#diff-a739ba3914e4e44366492e0305c5000673e34e958ed59e267ae0b678673bca6fR220 instead both for visibility and for symmetrie (or consistency). Let me demo a pull request for that variant, upcoming.
    Also, #139460 would cause conflicts otherwise. I'm still hoping for review on that one from someone. I believe it's keeping things short enough while still giving some more guidance users.

  19. added a commit that references this issue on Oct 14, 2025
  20. added 2 commits that reference this issue on Nov 2, 2025
  21. added 2 commits that reference this issue on Nov 25, 2025
  22. added a commit that references this issue on Dec 17, 2025
  23. added a commit that references this issue on May 26, 2026
  24. added 2 commits that reference this issue on Jun 9, 2026
  25. added 2 commits that reference this issue on Jun 24, 2026
  26. added a commit that references this issue on Aug 4, 2026
  27. added 2 commits that reference this issue on Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions