Trusted Types &
Dynamic Code Brand Checks
2025/02/27�@hiroppy
Trusted Types
Bad Examples
Content-Security-Policy
Content-Security-Policy: trusted-types;
Content-Security-Policy: trusted-types 'none';
Content-Security-Policy: trusted-types <policyName>;
Content-Security-Policy: trusted-types <policyName> <policyName> 'allow-duplicates';
Content-Security-Policy: require-trusted-types-for 'script';
Refused to create a TrustedTypePolicy named 'myPolicy' because it violates the following Content Security Policy directive: "trusted-types ".�
Uncaught TypeError: Failed to execute 'createPolicy' on 'TrustedTypePolicyFactory': Policy "myPolicy" disallowed.
Injection Sinks
e.g. HTMLをサニタイズし安全に作る
content-security-policy: trusted-types foo;
const escapeHTMLPolicy = trustedTypes.createPolicy("foo", {
createHTML: (string) =>
string
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/"/g, """)
.replace(/'/g, "'"),
});
const escaped = escapeHTMLPolicy.createHTML("<img src=x onerror=alert(1)>");
el.innerHTML = escaped;
// bad
el.innerHTML = "<img src=x onerror=alert(1)>";
e.g. scriptの実行を阻止する
content-security-policy: require-trusted-types-for 'script'
eval("alert('Hello!');");
This document requires 'TrustedScript' assignment.
Uncaught EvalError: Refused to evaluate a string as JavaScript because this document requires 'Trusted Type' assignment.
content-security-policy: require-trusted-types-for 'script'; trusted-types foo;
const policy = trustedTypes.createPolicy("foo", { createScript: (string) => string });
const safeScript = policy.createScript("alert('Hello!');");
eval(safeScript);
V8 option via Node.js
$ cat script.js
$ eval("console.log('hi!')")
$ node script.js
$ hi!
$ node --disallow_code_generation_from_strings script.js # runtimeで実行中に落ちる
$ EvalError: Code generation from strings disallowed for this context
👍 (new Function("console.log('hi!')"))(); なども同様
Dynamic Code Brand Checks
�stage3
Motivation
> eval is Evil
> The eval function is the most misused feature of JavaScript. Avoid it.
> -- Douglas Crockford, "JavaScript: The Good Parts"
Brand Check?
const map = new Map();
const obj = {};
obj.get = map.get;
try {
// [[MapData]] internal slot
console.log(obj.get('foo'));
} catch (error) {
// TypeError: Method Map.prototype.get called on incompatible receiver #<Object>
}
Spec Goal
HostEnsureCanCompileStrings( calleeRealm, parameterStrings, bodyString, direct )
👇
HostEnsureCanCompileStrings( calleeRealm, parameterStrings, bodyString, codeString, compilationType, parameterArgs, bodyArg )
仕様上の抽象操作の一つで、実行環境が文字列からECMAScriptコードに動的にコンパイルする際に呼び出されるフックであり、ブロックしたり呼び出していいかをチェックします
他にも言語仕様書で定義される抽象操作のHostGetCodeForEval、HostEnsureCanCompileStrings、PerformEval、CreateDynamicFunctionが追加・変更される
Goal
Wrapping Up