Skip to content

Unmatched </p> or </br> inside foreign context needs a special parser rule #5113

Description

@mfreed7

As the current parser spec is written, <svg></p></svg> and <svg></br></svg> both result in <p> and <br> DOM nodes as children of the <svg>. As mentioned in this Chromium bug and this blog post, this can be exploited as a sanitizer bypass. Here is an example DOM Viewer link showing the behavior.

By my reading of the spec:

  • In the "in body" insertion mode, for a </p> tag, if the stack of open elements does not have a p element in button scope, then this is a parse error; insert an HTML element for a "p" start tag token with no attributes. Close a p element. (This adds the <p> within <svg>.)
  • When parsing tokens in a foreign context, when "Any other end tag" is encountered, nothing special happens in this case, for a </p> found within an <svg>. Normal processing (the bullet point above) happens in step 7. All of the special "jumping out" behavior is specified for the start tags only, a bit higher up in the foreign context section. For those, the behavior is: Pop an element from the stack of open elements, and then keep popping more elements from the stack of open elements until the current node is a MathML text integration point, an HTML integration point, or an element in the HTML namespace. (This is what causes a <p> found within <svg> to close the </svg> and leave the <p> outside.)

Current implementations:

  • Blink leaves the <p> or <br> inside <svg>.
  • Webkit leaves the <p> or <br> inside <svg>.
  • Gecko (correctly?) moves the <p> or <br> outside the <svg>.

I believe the spec should follow current Gecko behavior. I think the easiest way to change the spec would be to add a special case within the foreign context section for end tags whose tag name is "p" or "br", which closes the foreign context and then processes the </p> or </br> as normal for a non-foreign context.

Activity

  1. domenic commented on Nov 27, 2019

    @domenic
    Member

    /cc @whatwg/html-parser

  2. bathos commented on Nov 27, 2019

    @bathos

    (Additional impl data:) parse5 is currently consistent with Blink/Webkit

  3. mfreed7 commented on Nov 27, 2019

    @mfreed7
    ContributorAuthor

    I should also have referenced the corresponding Chromium bug.

  4. sideshowbarker commented on Nov 28, 2019

    @sideshowbarker
    Member

    html5lib leaves the <p> or <br> inside <svg>:

    $ echo "<svg></p></svg>" | python -c "from sys import stdin; \
    import html5lib; from lxml import html; \
    doc = html5lib.parse(stdin, treebuilder='lxml', namespaceHTMLElements=False); \
    print html.tostring(doc)"
    <html><head></head><body><ns0:svg xmlns:ns0="http://www.w3.org/2000/svg"><p></p></ns0:svg>
    </body></html>
    
    $ echo "<svg></br></svg>" | python -c "from sys import stdin; \
    import html5lib; from lxml import html; \
    doc = html5lib.parse(stdin, treebuilder='lxml', namespaceHTMLElements=False); \
    print html.tostring(doc)"
    <html><head></head><body><ns0:svg xmlns:ns0="http://www.w3.org/2000/svg"><br></ns0:svg>
    </body></html>
    
  5. annevk commented on Dec 2, 2019

    @annevk
    Member

    @mfreed7 could you copy @hsivonen and I on the Chrome issue (or unhide it now that you and others essentially made it public)?

  6. mfreed7 commented on Dec 2, 2019

    @mfreed7
    ContributorAuthor

    No problem - I just marked it all public. I had essentially been treating it as public given the blog post.

  7. added a commit that references this issue on Mar 10, 2020
  8. 1 remaining item

  9. gsnedders commented on Jan 26, 2021

    @gsnedders
    Member

    While in general I'm pretty reluctant to change the parser, this seems like an obvious oversight in the current parser (given the odd </p>/</br> parsing), and hence I'd support changing the behaviour to match Gecko here.

  10. securityMB commented on Feb 2, 2021

    @securityMB

    Here's another sanitizer bypass that appears to be caused by the same issue: GHSA-vv2x-vrpj-qqpq

  11. zcorpan commented on Feb 26, 2021

    @zcorpan
    Member

    When writing tests for this, here's one for html5lib foreign-fragment.dat, but should also test this in regular parsing mode (without #document-fragment)

    #data
    <svg></p><foo>
    #errors
    9: HTML end tag “p” in a foreign namespace context.
    #document-fragment
    div
    #document
    | <svg svg>
    | <p>
    | <foo>
    
  12. added a commit that references this issue on Jun 4, 2021
    5333b04
  13. added a commit that references this issue on Jun 23, 2021
    681c884
  14. added a commit that references this issue on Jul 26, 2021
  15. added a commit that references this issue on Jun 3, 2022
    de48aa4
  16. added a commit that references this issue on May 28, 2025
  17. added a commit that references this issue on Sep 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions