mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-31 03:41:51 +00:00
fix: hash inline scripts with data-src attributes
This commit is contained in:
@@ -55,6 +55,15 @@ describe("computeInlineScriptHashes", () => {
|
||||
expect(hashes).toEqual([]);
|
||||
});
|
||||
|
||||
it("does not treat data-src as an external script attribute", () => {
|
||||
const content = "console.log('inline')";
|
||||
const expected = createHash("sha256").update(content, "utf8").digest("base64");
|
||||
const hashes = computeInlineScriptHashes(
|
||||
`<html><script data-src="/app.js">${content}</script></html>`,
|
||||
);
|
||||
expect(hashes).toEqual([`sha256-${expected}`]);
|
||||
});
|
||||
|
||||
it("hashes only inline scripts when mixed with external", () => {
|
||||
const inlineContent = "console.log('init')";
|
||||
const expected = createHash("sha256").update(inlineContent, "utf8").digest("base64");
|
||||
|
||||
@@ -10,7 +10,7 @@ export function computeInlineScriptHashes(html: string): string[] {
|
||||
let match: RegExpExecArray | null;
|
||||
while ((match = re.exec(html)) !== null) {
|
||||
const openTag = match[0].slice(0, match[0].indexOf(">") + 1);
|
||||
if (/\bsrc\s*=/i.test(openTag)) {
|
||||
if (hasScriptSrcAttribute(openTag)) {
|
||||
continue;
|
||||
}
|
||||
const content = match[1];
|
||||
@@ -23,6 +23,60 @@ export function computeInlineScriptHashes(html: string): string[] {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
function hasScriptSrcAttribute(openTag: string): boolean {
|
||||
let i = openTag.search(/\bscript\b/i);
|
||||
if (i < 0) {
|
||||
return false;
|
||||
}
|
||||
i += "script".length;
|
||||
while (i < openTag.length) {
|
||||
while (i < openTag.length && /\s/.test(openTag[i] ?? "")) {
|
||||
i += 1;
|
||||
}
|
||||
const current = openTag[i];
|
||||
if (!current || current === ">") {
|
||||
return false;
|
||||
}
|
||||
if (current === "/") {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
const nameStart = i;
|
||||
while (i < openTag.length && /[^\s=/>]/.test(openTag[i] ?? "")) {
|
||||
i += 1;
|
||||
}
|
||||
const attributeName = openTag.slice(nameStart, i).toLowerCase();
|
||||
if (attributeName === "src") {
|
||||
return true;
|
||||
}
|
||||
while (i < openTag.length && /\s/.test(openTag[i] ?? "")) {
|
||||
i += 1;
|
||||
}
|
||||
if ((openTag[i] ?? "") !== "=") {
|
||||
continue;
|
||||
}
|
||||
i += 1;
|
||||
while (i < openTag.length && /\s/.test(openTag[i] ?? "")) {
|
||||
i += 1;
|
||||
}
|
||||
const quote = openTag[i];
|
||||
if (quote === '"' || quote === "'") {
|
||||
i += 1;
|
||||
while (i < openTag.length && openTag[i] !== quote) {
|
||||
i += 1;
|
||||
}
|
||||
if (openTag[i] === quote) {
|
||||
i += 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
while (i < openTag.length && /[^\s>]/.test(openTag[i] ?? "")) {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function buildControlUiCspHeader(opts?: { inlineScriptHashes?: string[] }): string {
|
||||
const hashes = opts?.inlineScriptHashes;
|
||||
const scriptSrc = hashes?.length
|
||||
|
||||
Reference in New Issue
Block a user