summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Nate Moore <natemoo-re@users.noreply.github.com> 2022-03-09 17:02:25 -0600
committerGravatar GitHub <noreply@github.com> 2022-03-09 17:02:25 -0600
commit05b66bd68b173d30921c9f0565b3dc2379039fcd (patch)
treeb87d0db458dc7b5594556dc58a9e25db1f1aca4b
parent658a92915d27b10c34ad94003c6344cd37f093d7 (diff)
downloadastro-05b66bd68b173d30921c9f0565b3dc2379039fcd.tar.gz
astro-05b66bd68b173d30921c9f0565b3dc2379039fcd.tar.zst
astro-05b66bd68b173d30921c9f0565b3dc2379039fcd.zip
Escape HTML by default (#2747)
* feat: escape HTML by default * feat(test): add escaping test
-rw-r--r--.changeset/sour-socks-enjoy.md5
-rw-r--r--packages/astro/package.json4
-rw-r--r--packages/astro/src/runtime/server/escape.ts19
-rw-r--r--packages/astro/src/runtime/server/index.ts4
-rw-r--r--packages/astro/test/astro-expr.test.js9
-rw-r--r--packages/astro/test/fixtures/astro-expr/src/pages/escape.astro9
-rw-r--r--pnpm-lock.yaml11
7 files changed, 35 insertions, 26 deletions
diff --git a/.changeset/sour-socks-enjoy.md b/.changeset/sour-socks-enjoy.md
new file mode 100644
index 000000000..aa9b56485
--- /dev/null
+++ b/.changeset/sour-socks-enjoy.md
@@ -0,0 +1,5 @@
+---
+'astro': minor
+---
+
+Escape HTML inside of expressions by default. Please see [our migration guide](https://docs.astro.build/en/migrate/#deprecated-unescaped-html) for more details.
diff --git a/packages/astro/package.json b/packages/astro/package.json
index 69818591e..d3dea5a39 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -58,7 +58,7 @@
"test:match": "mocha --timeout 20000 -g"
},
"dependencies": {
- "@astrojs/compiler": "^0.12.0-next.8",
+ "@astrojs/compiler": "^0.12.0-next.9",
"@astrojs/language-server": "^0.8.6",
"@astrojs/markdown-remark": "^0.6.4",
"@astrojs/prism": "0.4.0",
@@ -95,10 +95,10 @@
"resolve": "^1.20.0",
"rollup": "^2.64.0",
"semver": "^7.3.5",
- "sirv": "^2.0.2",
"serialize-javascript": "^6.0.0",
"shiki": "^0.10.0",
"shorthash": "^0.0.2",
+ "sirv": "^2.0.2",
"slash": "^4.0.0",
"sourcemap-codec": "^1.4.8",
"srcset-parse": "^1.1.0",
diff --git a/packages/astro/src/runtime/server/escape.ts b/packages/astro/src/runtime/server/escape.ts
index a0482fdf2..6c6eb4ff6 100644
--- a/packages/astro/src/runtime/server/escape.ts
+++ b/packages/astro/src/runtime/server/escape.ts
@@ -1,23 +1,6 @@
const entities = { '"': 'quot', '&': 'amp', "'": 'apos', '<': 'lt', '>': 'gt' } as const;
-const warned = new Set<string>();
-export const escapeHTML = (string: any, { deprecated = false }: { deprecated?: boolean } = {}) => {
- const escaped = string.replace(/["'&<>]/g, (char: keyof typeof entities) => '&' + entities[char] + ';');
- if (!deprecated) return escaped;
- if (warned.has(string) || !string.match(/[&<>]/g)) return string;
- // eslint-disable-next-line no-console
- console.warn(`Unescaped HTML content found inside expression!
-
-The next minor version of Astro will automatically escape all
-expression content. Please use the \`set:html\` directive.
-
-Expression content:
-${string}`);
- warned.add(string);
-
- // Return unescaped content for now. To be removed.
- return string;
-};
+export const escapeHTML = (string: any) => string.replace(/["'&<>]/g, (char: keyof typeof entities) => '&' + entities[char] + ';');
/**
* RawString is a "blessed" version of String
diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts
index 19affdb0b..d2a022805 100644
--- a/packages/astro/src/runtime/server/index.ts
+++ b/packages/astro/src/runtime/server/index.ts
@@ -8,7 +8,7 @@ import { escapeHTML, UnescapedString, unescapeHTML } from './escape.js';
export type { Metadata } from './metadata';
export { createMetadata } from './metadata.js';
-export { escapeHTML, unescapeHTML } from './escape.js';
+export { unescapeHTML } from './escape.js';
const voidElementNames = /^(area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/i;
const htmlBooleanAttributes =
@@ -36,7 +36,7 @@ async function _render(child: any): Promise<any> {
// of wrapping it in a function and calling it.
return _render(child());
} else if (typeof child === 'string') {
- return escapeHTML(child, { deprecated: true });
+ return escapeHTML(child);
} else if (!child && child !== 0) {
// do nothing, safe to ignore falsey values.
}
diff --git a/packages/astro/test/astro-expr.test.js b/packages/astro/test/astro-expr.test.js
index e08323f86..e996062b5 100644
--- a/packages/astro/test/astro-expr.test.js
+++ b/packages/astro/test/astro-expr.test.js
@@ -99,4 +99,13 @@ describe('Expressions', () => {
// test 9: Expected {undefined && <span id="undefined" />} not to render
expect($('#frag-undefined')).to.have.lengthOf(0);
});
+
+ it('Escapes HTML by default', async () => {
+ const html = await fixture.readFile('/escape/index.html');
+ const $ = cheerio.load(html);
+
+ expect($('body').children()).to.have.lengthOf(1);
+ expect($('body').text()).to.include('&lt;script&gt;console.log(&quot;pwnd&quot;)&lt;/script&gt;')
+ expect($('#trusted')).to.have.lengthOf(1);
+ });
});
diff --git a/packages/astro/test/fixtures/astro-expr/src/pages/escape.astro b/packages/astro/test/fixtures/astro-expr/src/pages/escape.astro
new file mode 100644
index 000000000..8c16d7fd2
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-expr/src/pages/escape.astro
@@ -0,0 +1,9 @@
+<html lang="en">
+<head>
+ <title>My site</title>
+</head>
+<body>
+ {'<script>console.log("pwnd")</script>'}
+ <Fragment set:html={'<script id="trusted">console.log("yay!")</script>'} />
+</body>
+</html>
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f66275bda..b1f75c17c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -340,7 +340,7 @@ importers:
packages/astro:
specifiers:
- '@astrojs/compiler': ^0.12.0-next.8
+ '@astrojs/compiler': ^0.12.0-next.9
'@astrojs/language-server': ^0.8.6
'@astrojs/markdown-remark': ^0.6.4
'@astrojs/parser': ^0.22.1
@@ -414,7 +414,7 @@ importers:
yargs-parser: ^21.0.0
zod: ^3.8.1
dependencies:
- '@astrojs/compiler': 0.12.0-next.8
+ '@astrojs/compiler': 0.12.0-next.9
'@astrojs/language-server': 0.8.10
'@astrojs/markdown-remark': link:../markdown/remark
'@astrojs/prism': link:../astro-prism
@@ -1328,10 +1328,12 @@ packages:
leven: 3.1.0
dev: true
- /@astrojs/compiler/0.12.0-next.8:
- resolution: {integrity: sha512-HeREaw5OR5J7zML+/LxhrqUr57571kyNXL4HD2pU929oevhx3PQ37PQ0FkD5N65X9YfO+gcoEO6whl76vtSZag==}
+ /@astrojs/compiler/0.12.0-next.9:
+ resolution: {integrity: sha512-XHvGrPBhr/LBYZT4TuXf8mK2+CYCClQoPln9FlF6gIx4yTsWpUwAi3mhhFOGJi4NB1Y1ZbcXS60IjMy/2adpLg==}
dependencies:
+ tsm: 2.2.1
typescript: 4.6.2
+ uvu: 0.5.3
dev: false
/@astrojs/language-server/0.8.10:
@@ -8788,6 +8790,7 @@ packages:
/source-map/0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
+ requiresBuild: true
/source-map/0.7.3:
resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==}