]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-vapor): escape html for safer template output (#13919)
authoredison <daiwei521@126.com>
Wed, 24 Sep 2025 08:56:36 +0000 (16:56 +0800)
committerGitHub <noreply@github.com>
Wed, 24 Sep 2025 08:56:36 +0000 (16:56 +0800)
packages/compiler-vapor/__tests__/transforms/transformText.spec.ts
packages/compiler-vapor/src/transforms/transformComment.ts
packages/compiler-vapor/src/transforms/transformText.ts

index 20fa6d1fd008861d359be28b9fe1f0097af5cdb9..dbff56f2a425dad10ba7dba5532ea783a232ef2a 100644 (file)
@@ -48,4 +48,10 @@ describe('compiler: text transform', () => {
     expect(ir.block.operation).toMatchObject([])
     expect(ir.block.effect.length).toBe(1)
   })
+
+  it('escapes raw static text when generating the template string', () => {
+    const { ir } = compileWithTextTransform('<code>&lt;script&gt;</code>')
+    expect(ir.template).toContain('<code>&lt;script&gt;</code>')
+    expect(ir.template).not.toContain('<code><script></code>')
+  })
 })
index 23c4069551fff91337797c120294c9100326696a..f85498febce3747c67167f7e6997948846e6b36c 100644 (file)
@@ -6,6 +6,7 @@ import {
 } from '@vue/compiler-dom'
 import type { NodeTransform, TransformContext } from '../transform'
 import { DynamicFlag } from '../ir'
+import { escapeHtml } from '@vue/shared'
 
 export const transformComment: NodeTransform = (node, context) => {
   if (node.type !== NodeTypes.COMMENT) return
@@ -14,7 +15,7 @@ export const transformComment: NodeTransform = (node, context) => {
     context.comment.push(node)
     context.dynamic.flags |= DynamicFlag.NON_TEMPLATE
   } else {
-    context.template += `<!--${node.content}-->`
+    context.template += `<!--${escapeHtml(node.content)}-->`
   }
 }
 
index e9c273b85c73f583a3ed0261e4f2a1e19722255a..dd81bec1e80415d28621da677d815c941968f536 100644 (file)
@@ -16,6 +16,7 @@ import {
   isConstantExpression,
   isStaticExpression,
 } from '../utils'
+import { escapeHtml } from '@vue/shared'
 
 type TextLike = TextNode | InterpolationNode
 const seen = new WeakMap<
@@ -82,7 +83,7 @@ export const transformText: NodeTransform = (node, context) => {
   } else if (node.type === NodeTypes.INTERPOLATION) {
     processInterpolation(context as TransformContext<InterpolationNode>)
   } else if (node.type === NodeTypes.TEXT) {
-    context.template += node.content
+    context.template += escapeHtml(node.content)
   }
 }
 
@@ -143,7 +144,7 @@ function processTextContainer(
   const literals = values.map(getLiteralExpressionValue)
 
   if (literals.every(l => l != null)) {
-    context.childrenTemplate = literals.map(l => String(l))
+    context.childrenTemplate = literals.map(l => escapeHtml(String(l)))
   } else {
     context.childrenTemplate = [' ']
     context.registerOperation({