Compare commits

...
Author SHA1 Message Date
Yang JunandCursor 90abadfc39 docs(strip_html): clarify output is not HTML-safe
Reword the warning to note string scanning vs HTML5 parsing, without
listing specific bypass cases.

Co-authored-by: Cursor <[email protected]>
2026-06-22 01:55:30 +08:00
Yang JunandCursor f64f04c562 fix(strip_html): avoid infinite loop on unclosed openers
Change the stall guard from i === lt to i <= lt (GHSA-m7fp-h3p4-hr49).
Document that strip_html output is not safe for HTML without escape.

Co-authored-by: Cursor <[email protected]>
2026-06-22 01:43:34 +08:00
4 changed files with 14 additions and 1 deletions
+1
View File
@@ -11,6 +11,7 @@ coverage/
node_modules/
# tmp
.local/
docs/themes/navy/source/js/liquid.browser.min.js
docs/themes/navy/layout/partial/all-contributors.swig
docs/themes/navy/layout/partial/financial-contributors.swig
+8
View File
@@ -6,6 +6,10 @@ title: strip_html
Removes any HTML tags from a string.
{% note warn Not safe for HTML output %}
This filter removes tags by string scanning; it does not parse HTML5 the way a browser does, and it is not a sanitizer. The result may still be unsafe when inserted into HTML. Use [escape][escape], [escape_once][escape_once], or [`outputEscape: "escape"`][outputEscape] for untrusted output.
{% endnote %}
Input
```liquid
{{ "Have <em>you</em> read <strong>Ulysses</strong>?" | strip_html }}
@@ -15,3 +19,7 @@ Output
```text
Have you read Ulysses?
```
[escape]: ./escape.html
[escape_once]: ./escape.html
[outputEscape]: ../tutorials/options.html#outputEscape
+1 -1
View File
@@ -60,7 +60,7 @@ export function strip_html (this: FilterImpl, v: string) {
if (e >= 0) { i = e + closer.length; break }
blocks.delete(opener)
}
if (i === lt) return out + str.slice(lt)
if (i <= lt) return out + str.slice(lt)
}
return out
}
+4
View File
@@ -85,5 +85,9 @@ describe('filters/html', function () {
expect(liquid.parseAndRenderSync('{{"<img\rsrc=x\ronerror=alert(1)>" | strip_html}}')).toBe('')
expect(liquid.parseAndRenderSync('{{"<svg\nonload=alert(1)>" | strip_html}}')).toBe('')
})
it('should not loop on unclosed openers (GHSA-m7fp-h3p4-hr49)', function () {
expect(liquid.parseAndRenderSync('{{ "a<" | strip_html }}')).toBe('a<')
expect(liquid.parseAndRenderSync('{{ "hello<world<again" | strip_html }}')).toBe('hello<world<again')
})
})
})