0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

Fix an issue where dev toolbar x-ray didn't escape props content (#10400)

* fix(toolbar): fix an issue where x-ray didn't escape props content

* test(toolbar): add a test case related to x-ray

* chore: add changeset
This commit is contained in:
Ming-jun Lu 2024-03-12 19:30:11 +08:00 committed by GitHub
parent a49892349e
commit 629c9d7c4d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 5 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Fixes an issue where dev toolbar x-ray didn't escape props content.

View file

@ -100,6 +100,34 @@ test.describe('Dev Toolbar', () => {
await expect(xrayHighlightTooltip).not.toBeVisible();
});
test('xray escapes props content', async ({ page, astro }) => {
let isAlertCalled = false;
page.on('dialog', async (dialog) => {
isAlertCalled = true;
await dialog.accept();
});
await page.goto(astro.resolveUrl('/xray-props-escape'));
const toolbar = page.locator('astro-dev-toolbar');
const appButton = toolbar.locator('button[data-app-id="astro:xray"]');
await appButton.click();
const xrayCanvas = toolbar.locator('astro-dev-toolbar-app-canvas[data-app-id="astro:xray"]');
const xrayHighlight = xrayCanvas.locator('astro-dev-toolbar-highlight');
await expect(xrayHighlight).toBeVisible();
await xrayHighlight.hover();
const xrayHighlightTooltip = xrayHighlight.locator('astro-dev-toolbar-tooltip');
await expect(xrayHighlightTooltip).toBeVisible();
const code = xrayHighlightTooltip.locator('pre > code');
await expect(code).toHaveText(
JSON.stringify({ name: `<img src='' onerror='alert(1)'>` }, undefined, 2)
);
expect(isAlertCalled).toBe(false);
});
test('xray shows no islands message when there are none', async ({ page, astro }) => {
await page.goto(astro.resolveUrl('/xray-no-islands'));

View file

@ -0,0 +1,9 @@
---
import { HelloWorld } from '../components/HelloWorld';
---
<h1>Hello World</h1>
<HelloWorld
name={`<img src='' onerror='alert(1)'>`}
client:load
/>

View file

@ -1,3 +1,4 @@
import { escape as escapeHTML } from 'html-escaper';
import type { DevToolbarApp, DevToolbarMetadata } from '../../../../@types/astro.js';
import type { DevToolbarHighlight } from '../ui-library/highlight.js';
import {
@ -137,13 +138,14 @@ export default {
(prop: any) => !prop[0].startsWith('data-astro-cid-')
);
if (islandPropsEntries.length > 0) {
const stringifiedProps = JSON.stringify(
Object.fromEntries(islandPropsEntries.map((prop: any) => [prop[0], prop[1][1]])),
undefined,
2
);
tooltip.sections.push({
title: 'Props',
content: `<pre><code>${JSON.stringify(
Object.fromEntries(islandPropsEntries.map((prop: any) => [prop[0], prop[1][1]])),
undefined,
2
)}</code></pre>`,
content: `<pre><code>${escapeHTML(stringifiedProps)}</code></pre>`,
});
}