

Vue.js 因停用 CSP unsafe-eval 崩壞之初步研究
source link: https://blog.darkthread.net/blog/vue3-n-unsafe-eval/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Vue.js 因停用 CSP unsafe-eval 崩壞之初步研究-黑暗執行緒
讀者 Kg 分享,我愛用的 Vue 3.0 輕前端寫法若遭遇資安政策要求禁用 CSP script-src 'unsafe-eval' 將會失效。登楞!!!
研究了一下,Vue 超方便的 template 寫法 template: '<div>{{ message }}</div>'
,底層需要 eval 函式才能運作:
const app = Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
},
template: '<div>{{ message }}</div>'
});
因此,若網站或網頁啟用 CSP script-src 但沒開放 'unsafe-eval',將導致 Vue 3.0 噴出錯誤:「Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self'".」,用以下 HTML 可重現問題:
<!DOCTYPE html>
<html>
<head>
<title>My Vue App</title>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
</head>
<body>
<div id="app"></div>
<script src="vue.global.prod.min.js"></script>
<script src="app.js"></script>
</body>
</html>
執行後看不到 Hello Vue! 且出現錯誤:
要解決這類問題,~~一概建議先解決資安人員(大誤)~~正統做法是回歸預先編譯,搬 webpack 出來並加上編譯程序,但如此形同棄守輕前端。
我找到第二條路,用 render 取代 template,無奈改用 render() 的寫法超級囉嗦,Vue 的輕巧易用特性盡失,難以視為替代方案。但我還是試寫一段體驗:
註:h() 的用法可參考官方文件,概念接近 .NET System.Xml.Linq 宣告 XElement 的玩法,不難理解。
let h = Vue.h;
const app = Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
},
render() {
return h('div',
{ 'id': 'demo', 'class': 'my-css'},
[
'Hello, Vue!',
h('p', 'simple text only paragraph'),
h('p', { 'class': 'p-css' }, [
h('span', 'Nested Span')
])
]
);
}
})
app.mount('#app')
將 Vue 程式庫換成 vue.runtime.global.prod.min.js,搭配 render() 版本,即可在 CSP 嚴格限制下忍辱偷生:
但是,寫慣 template 字串式宣告後應該沒人能接受這種折磨,更甭提把所有 template 語法改成這副德行。
使用 JSX 語法配合 babel-plugin-jsx 是另一個解決方向,JAX 會像這樣:
// app.jsx
const app = Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
},
render() {
<div>{{ message }}</div>
}
});
app.mount('#app');
簡潔度與 template 相去不遠,但缺點是 jsx 也需要事前編譯,且需要學習 JSX 語法,與輕前端的理念不符。
結論:想在 CSP 不允許 unsafe-eval 的環境使用 Vue 3 輕前端寫法,目前無解,想突圍只能棄守改用預先編譯。
傳統 JavaScript 程式依賴 eval() 寫法的場合蠻遍的,全面禁止會血流成河似乎也在預期之內,衝擊跟全面禁止 HTTP 一律用 HTTPS 差不多,故猜想短期還不致全面強制推行,但心理可能要先有底了。
【參考資料】
</div
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK