57 lines
1.9 KiB
JavaScript
57 lines
1.9 KiB
JavaScript
// Robustness guards shared by compile.js (overlay) AND sassCompile.js (Phase 2).
|
|
// NOT a security boundary (see README SECURITY section): an admin can already
|
|
// inject site CSS/JS by other means. These exist solely so a single malformed
|
|
// token value cannot white-screen every page -- a value that could close a CSS
|
|
// block early ("}"), terminate a declaration (";"), or open/close a comment is
|
|
// DROPPED from output (not escaped), confining each token to its own declaration.
|
|
|
|
const { MAX_VALUE_LEN } = require("./tokenSchema");
|
|
|
|
// Substrings that would let a value escape its own declaration/block.
|
|
const BAD_SUBSTRINGS = ["{", "}", ";", "</", "/*", "*/"];
|
|
|
|
|
|
// Returns the value unchanged if safe to emit, or null if it must be dropped.
|
|
// When dropped, pushes a human-readable note onto the optional warnings array.
|
|
function sanitizeValue(value, warnings) {
|
|
if (value == null) {
|
|
return null;
|
|
}
|
|
const v = String(value);
|
|
if (v.length > MAX_VALUE_LEN) {
|
|
if (warnings) {
|
|
warnings.push(`value dropped (too long): ${v.slice(0, 24)}...`);
|
|
}
|
|
return null;
|
|
}
|
|
for (const bad of BAD_SUBSTRINGS) {
|
|
if (v.includes(bad)) {
|
|
if (warnings) {
|
|
warnings.push(`value dropped (illegal "${bad}")`);
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
return v;
|
|
}
|
|
|
|
|
|
// Returns a conservative selector unchanged, or null if it could break out of a
|
|
// rule block. Selectors come only from TOKEN_SCHEMA (trusted), but we guard
|
|
// anyway so a future data-driven selector cannot escape.
|
|
function sanitizeSelector(selector) {
|
|
if (selector == null) {
|
|
return null;
|
|
}
|
|
const s = String(selector);
|
|
if (s.length > 256) {
|
|
return null;
|
|
}
|
|
if (/[{};<>]/.test(s) || s.includes("/*") || s.includes("*/")) {
|
|
return null;
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
module.exports = { sanitizeValue, sanitizeSelector };
|