Skip to content

Commit 0b3b710

Browse files
committed
🔒️ Fix HTML entity escaping in SignalRGB meta tag generation
Add escapeHtml utility function to properly sanitize special characters in meta tag attributes to prevent HTML injection vulnerabilities. The function handles &, ", <, and > characters which are commonly found in user-controlled content like effect names, descriptions, and control labels. This ensures meta tags remain valid HTML and prevents potential security issues. Updates meta tag format to match SignalRGB's expected structure with proper self-closing tags and correct attribute names (description → description, author → publisher).
1 parent 7fa72b8 commit 0b3b710

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

packages/dev/plugins/signalrgb.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ const logger = {
5656
},
5757
}
5858

59+
/**
60+
* Escape HTML entities in a string for use in meta tag attributes
61+
*/
62+
function escapeHtml(str: string): string {
63+
return str.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
64+
}
65+
5966
/**
6067
* Generate meta tags from control definitions extracted via reflect-metadata
6168
*/
@@ -74,39 +81,40 @@ function generateMetaTags(
7481
): string {
7582
let metaTags = ''
7683

77-
// Effect metadata
78-
metaTags += `<meta name="name" content="${effectMetadata.name}">\n`
84+
// Effect metadata (SignalRGB format)
7985
if (effectMetadata.description) {
80-
metaTags += `<meta name="description" content="${effectMetadata.description}">\n`
86+
metaTags += `<meta description="${escapeHtml(effectMetadata.description)}"/>\n`
8187
}
8288
if (effectMetadata.author) {
83-
metaTags += `<meta name="author" content="${effectMetadata.author}">\n`
89+
metaTags += `<meta publisher="${escapeHtml(effectMetadata.author)}"/>\n`
8490
}
8591

8692
// Control meta tags
8793
for (const control of controls) {
88-
const tooltip = control.tooltip ? ` tooltip="${control.tooltip}"` : ''
94+
const label = escapeHtml(control.label)
95+
const tooltip = control.tooltip ? ` tooltip="${escapeHtml(control.tooltip)}"` : ''
96+
const defaultVal = escapeHtml(String(control.default))
8997

9098
switch (control.type) {
9199
case 'number':
92-
metaTags += `<meta property="${control.id}" label="${control.label}" type="number" min="${control.min ?? 0}" max="${control.max ?? 100}" default="${control.default}"${tooltip}>\n`
100+
metaTags += `<meta property="${control.id}" label="${label}" type="number" min="${control.min ?? 0}" max="${control.max ?? 100}" default="${defaultVal}"${tooltip}/>\n`
93101
break
94102
case 'boolean':
95-
metaTags += `<meta property="${control.id}" label="${control.label}" type="boolean" default="${control.default}"${tooltip}>\n`
103+
metaTags += `<meta property="${control.id}" label="${label}" type="boolean" default="${defaultVal}"${tooltip}/>\n`
96104
break
97105
case 'combobox': {
98-
const values = (control.values ?? []).join(',')
99-
metaTags += `<meta property="${control.id}" label="${control.label}" type="combobox" values="${values}" default="${control.default}"${tooltip}>\n`
106+
const values = (control.values ?? []).map(escapeHtml).join(',')
107+
metaTags += `<meta property="${control.id}" label="${label}" type="combobox" values="${values}" default="${defaultVal}"${tooltip}/>\n`
100108
break
101109
}
102110
case 'hue':
103-
metaTags += `<meta property="${control.id}" label="${control.label}" type="hue" min="${control.min ?? 0}" max="${control.max ?? 360}" default="${control.default}"${tooltip}>\n`
111+
metaTags += `<meta property="${control.id}" label="${label}" type="hue" min="${control.min ?? 0}" max="${control.max ?? 360}" default="${defaultVal}"${tooltip}/>\n`
104112
break
105113
case 'color':
106-
metaTags += `<meta property="${control.id}" label="${control.label}" type="color" default="${control.default}"${tooltip}>\n`
114+
metaTags += `<meta property="${control.id}" label="${label}" type="color" default="${defaultVal}"${tooltip}/>\n`
107115
break
108116
case 'textfield':
109-
metaTags += `<meta property="${control.id}" label="${control.label}" type="textfield" default="${control.default}"${tooltip}>\n`
117+
metaTags += `<meta property="${control.id}" label="${label}" type="textfield" default="${defaultVal}"${tooltip}/>\n`
110118
break
111119
}
112120
}

0 commit comments

Comments
 (0)