1.0.37
This commit is contained in:
101 files changed
+5097
-642
No files matched your search
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Render a third-party template description (from a Portainer catalog) for
|
||||
* display via {@html}.
|
||||
*
|
||||
* The input is untrusted, so: HTML tags are stripped, and markdown links are
|
||||
* rebuilt only for safe http(s)/relative URLs — javascript:/data:/etc. are
|
||||
* dropped (keeping just the link text) to prevent a `[x](javascript:...)` XSS.
|
||||
*/
|
||||
|
||||
function escapeHtml(s: string): string {
|
||||
return s
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
}
|
||||
|
||||
// Only http(s) and relative URLs are safe to put in href; reject javascript:,
|
||||
// data:, etc.
|
||||
export function isSafeLinkUrl(url: string): boolean {
|
||||
// Browsers ignore ASCII whitespace/control chars when parsing the scheme, so
|
||||
// strip them before checking (defeats java\tscript: style bypasses).
|
||||
const cleaned = url.replace(/[\x00-\x20]/g, '').toLowerCase();
|
||||
if (cleaned.startsWith('http://') || cleaned.startsWith('https://')) return true;
|
||||
// No scheme (relative path/anchor) is safe; any other scheme is not.
|
||||
return !/^[a-z][a-z0-9+.-]*:/.test(cleaned);
|
||||
}
|
||||
|
||||
// Convert markdown links [text](url) to HTML <a> tags, strip other HTML.
|
||||
export function renderDescription(text: string): string {
|
||||
return text
|
||||
.replace(/<a\s+href="([^"]+)"[^>]*>([^<]+)<\/a>/gi, '[$2]($1)') // normalize HTML links to markdown first
|
||||
.replace(/<[^>]+>/g, '') // strip remaining HTML tags
|
||||
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_m, label: string, url: string) => {
|
||||
const safeText = escapeHtml(label);
|
||||
if (!isSafeLinkUrl(url)) return safeText; // drop unsafe scheme, keep the text
|
||||
return `<a href="${escapeHtml(url)}" target="_blank" rel="noopener" class="text-primary hover:underline">${safeText}</a>`;
|
||||
})
|
||||
.trim();
|
||||
}
|
||||
Reference in new issue
Block a user