务必定期检查应用的安全性,因为任何疏忽都可能使你自己、你的团队、你的用户甚至你的服务器面临严重漏洞的风险。不要因为自以为无所不知而忽略此页面。
¥DO periodically review the security of your application, because any lapse may be putting yourself, your team, your users and even your server at risk of serious exploitation. DON’T ignore this page because you think you know everything.
我们为安全字段的新手收集了一些最佳实践,并为刚接触 Vue 生态系统的安全专业人员提供了一些见解。随着我们通过自身研究以及杰出的安全社区的发布物了解到风险,我们将修改和添加本文档。
¥We have collected some best practices for those of you new to the security theater and a few insights for security professionals new to the Vue ecosystem. We will be revising and adding to this document as we become aware of risks through our own research and the publications of the amazing security community.
Vue 安全风险(Vue Security Risks)
¥Vue Security Risks
用户输入和 v-html 的风险(User Input and the Dangers of v-html)
¥User Input and the Dangers of v-html
v-html
指令是一种以编程方式渲染标记的绝佳方式,但即使是 Vue 文档也附带 这个警告:
¥The v-html
directive is a wonderful way to programmatically render markup, but even the Vue docs come with this warning:
"在你的网站上动态渲染任意 HTML 非常危险,因为它很容易导致 XSS 漏洞。仅对可信内容使用 HTML 插值,切勿对用户提供的内容使用。
¥“Dynamically rendering arbitrary HTML on your website can be very dangerous because it can easily lead to XSS vulnerabilities. Only use HTML interpolation on trusted content and never on user-provided content.”
如果你不明白这是什么意思,请快速浏览一下 OWASP 对 XSS(又称跨站点脚本攻击 (XSS) 的说明。
¥If you don’t know what that means, take a quick look at what OWASP has to say about XSS (aka cross-site scripting).
公平地说,这是个好建议,但不要太过复杂。请像攻击者一样思考,攻击者会通过创新、社交工程、撒谎、钓鱼和窃取你的系统。如果出现 Webpack 加载器漏洞,并以恶意方式更改了你的页面,该怎么办?如果有人恶意提交 PR,该怎么办?如果第三方 API 突然发生变化,发送的不是纯文本,而是结构相同但内容不同的文本,该怎么办?如果你认为安全的系统实际上被植入了后门,该怎么办?如果初级开发者对未经适当审查的代码进行了意外且具有根本威胁性的更改,该怎么办?(是的,愚蠢有时和恶意一样危险!)关键在于,务必做好应对最坏情况的准备,并强化所有系统,以防万一。
¥To be fair, this is good advice, but DON’T be all hand-wavy. DO think like an attacker who will innovate, social engineer, lie, phish and steal their way into your systems. What if a webpack loader exploit arises and changes your page in an evil way? What if someone makes a dastardly and ill-intentioned PR? What if suddenly a third party API changes and instead of plaintext starts sending the same structure but with different content? What if the systems you thought were safe turn out to actually have been backdoored? What if a junior dev makes an accidental and fundamentally threatening change to the code that isn’t reviewed properly? (Yes, idiocy is sometimes as dangerous as bad intentions!) The point is, DO anticipate the unexpected by preparing for the absolute worst case scenario and hardening all of your systems.
如果需要采取额外的预防措施,请使用 v-pre
指令。
¥DO use the v-pre
directive if you need to take extra precaution.
vue-i18n(vue-i18n)
Vue 的准官方国际化包允许你将 html 存储在键的值和 可能渲染它们 中。如果用户无法修改这些值,则应该没问题。 - 但请确保你信任(也就是审核)翻译人员!我们建议(尽管这会增加工作量并降低 HMR 的速度)务必使用 模板插值。
¥The quasi-official internationali(s/z)ation package for Vue allows you to store html in your key’s values and potentially render them. If users can’t modify these values, you should be ok - but make sure you trust (aka review) the translators! Our recommendation (although it is more work and will slow-down HMR) is DO use template interpolation.
eval()(eval())
即使你知道自己在做什么,你可能也想使用 eval()
,但请不要这样做。
¥Although you may be tempted to use eval()
, even if you know what you are doing, just DON’T.

¥
")
Quasar 组件(Quasar Components)
¥Quasar Components
某些 Quasar 组件和插件可以配置为允许渲染 “不安全内容”。这是一个可选功能,通过使用 *-html
类型的布尔值属性来实现。这些组件将在下文讨论。
¥Some Quasar components and Plugins can be configured to allow rendering of “insecure content”. This is an opt-in feature that is performed by using *-html
type boolean props. These components are discussed below.
QSelect(QSelect)
如果你没有自定义与菜单相关的作用域插槽(即 option
作用域插槽),请务必阻止组件在标签和子标签中渲染 HTML(通过不通过组件属性启用它)。一般来说,这不是用户提供的数据。如果你要自定义此插槽,则你有责任自行进行清理。
¥If you are not customizing menu-related scoped-slots (i.e. option
scoped slot), DO prevent the component from rendering HTML (by not enabling it through the component props) in the labels and sublabels. Generally speaking, this is not user-supplied data. If you are customizing this slot, it is your responsibility to do sanitization yourself.
QChat &表情符号(QChat & Emoji)
¥QChat & Emoji
QChatMessage
组件默认不以 HTML 格式显示内容。但是你可以启用它(通过 *-html
属性),在这种情况下你应该清理内容。
¥The QChatMessage
component does not display content as HTML by default. But you can enable it (through the *-html
props) in which case you should sanitize the content.
提示
最近出现了一些漏洞(尤其是在较旧的 Android 和 iOS 设备上),某些表情符号和非标准 UTF-8 编码实际上会触发移动设备重启和启动画面循环。请考虑在纯文本类型的输入字段中集成 Devland Markdown 解析,并在服务器端将其渲染为 HTML,然后再将其传递给聊天接收者。
¥There have been a number of recent exploits (especially for older Android and iOS devices) where certain emoji and non-standard UTF-8 actually triggered mobile device restarts and boot-screen loops. DO consider a devland integration of markdown parsing in a plain-text type of input field and render it to HTML on the server side before you pass it to the chat recipients.
加载中(Loading)
¥Loading
许多开发者要求 Loading 插件能够显示 HTML,因此默认启用了此功能。但如果你担心,请添加 sanitize: true
并删除矢量。
¥Many developers have asked that the Loading plugin be able to display HTML, so this was enabled by default, but if you are worried, DO add sanitize: true
and you removed the vector.
通知(Notify)
¥Notify
默认情况下,使用 HTML 设置通知插件的样式功能未启用,但如果你设置了布尔值属性 html: true
,则你有责任对其进行清理。
¥Being able to style the Notify plugin with HTML is not enabled by default, but if you do set the boolean prop html: true
then you are responsible for sanitizing it.
对话框(Dialog)
¥Dialog
默认情况下,使用 HTML 设置对话框插件的样式功能未启用,但如果你设置了布尔值属性 html: true
,则你有责任对其进行清理。
¥Being able to style the Dialog plugin with HTML is not enabled by default, but if you do set the boolean prop html: true
then you are responsible for sanitizing the title and message.
QInput(QInput)
任何允许用户输入键盘输入、从缓冲区粘贴或拖放文件的字段都存在安全风险。我们不会深入探讨其中的细节,但请记住,维护安全是你的责任。只有你才能防止帮助台火灾!
¥Any field that enables users to enter keystrokes, paste from the buffer or drop a file is a security risk. We won’t go into the nitty-gritty details of this, but just remember it is YOUR responsibility to maintain safety. Only you can prevent help-desk fires!
QEditor(QEditor)
此组件允许用户实际创建 HTML(甚至粘贴)。如果你要保存此文件并将其显示给其他用户,则需要在服务器端进行验证。如果是这样,请删除 <script></script>
和 <iframe></iframe>
。你可以访问文档中的 v-html 与 double-moustache 示例,试用 QEditor 组件,并了解这两种渲染方法将提供哪些功能。QEditor 没有 sanitize
标签。此外,如果你创建自定义按钮,你有责任确保它们的安全。你已收到警告。
¥This component allows the users to actually create HTML (and even paste it). If you are going to be saving this and showing it to other users, care will be needed on the server-side to validate it. In that case DO strip out <script></script>
and <iframe></iframe>
. You can visit the v-html vs. double-moustache example in the docs to play around with the QEditor component and see what the two rendering methods will provide. There is NO sanitize
tag for QEditor. Further, if you create custom buttons, it is your responsibility to make them safe. You have been warned.
文件处理(Dealing with Files)
¥Dealing with Files
那么,如何验证和清理文件呢?虽然这有点超出 “front-end-framework” 的范围,但我们知道很多读者也会将用户创建的文件存储在服务器上。如果你只是存储它们(而不以任何方式处理它们),请通过检测 魔法数字 来验证文件的类型是否正确。请考虑使用 ClamAV 检查文件是否存在已知病毒签名。
¥So how do you validate and sanitize a file? Well, although this is a bit out of scope for a “front-end-framework”, we know that many of you reading this will also be storing user-created files on servers. If you are just storing them (and not processing them in any way), DO validate that the file is of the appropriate type by detecting the magic numbers. DO consider using ClamAV to check files for known viral signatures.
图片(Images)
¥Images
如果你允许用户将图片上传到你的服务器,你应该知道许多常用模块仅检查文件后缀。制作一张表面上看起来像图片的图片很简单。请通过检查魔法数字来验证文件是否与其声明的一致,为此请考虑使用 is-image。虽然你可以在浏览器 使用此方法 中检查魔法数字,但另一种方法是让用户将图片加载到画布中,然后直接从画布上传。Vue-croppa 是一款出色的前端工具,可以完成此操作。
¥If you are allowing users to upload images to your server, you should know that many commonly used modules merely check the file suffix. It is trivial to craft an image that only superficially appears to be an image. DO verify that the file is what it claims to be by checking the magic numbers and for this consider using is-image. While you could check the magic number in the browser with this method, another approach is to let the user load an image into a canvas and then upload directly from the canvas. Vue-croppa is great front-end tool to do this.
存档(Archives)
¥Archives
用于目录遍历的存档解压攻击是一个真正的安全问题,如果不解压文件,几乎不可能检测到。如果你可以不接受这种类型的媒体,那就这样做吧。否则,在 Linux 上,请使用简单的 less
/ lesspipe
和 .lessfilter
来预处理这些文件,并配合你的自定义工作流程。
¥Archive decompression attacks for directory traversal are a real security issue and are virtually impossible to detect without decompressing the file. If you can get away with NOT accepting this type of media, then do it. Otherwise, on linux DO use the humble less
/ lesspipe
and .lessfilter
for preprocessing these files with your custom workflows.
密码(Passwords)
¥Passwords
实际上,不要以明文形式保存密码 - 根本不要保存它们。请保存安全哈希值,并根据使用安全盐和适当算法的方案在内存中计算它们。务必限制密码长度(包括最小和最大字符数),但要将上限设置得足够高,确保合法用户无法访问。请考虑使用高度安全的密码重置应用流程,并允许用户根据自己的偏好进行配置。每个项目都有其独特的流程,因此我们无法告诉你如何解决这个问题。不过,这里有一些不错的链接:
¥DON’T save passwords in plaintext, in fact - DON’T save them at all. DO save secure hashes and compute them in memory according to a scheme using secure salt and proper algorithms. DO limit the length of passwords (both minimum and maximum number of characters) BUT make the upper limit high enough that no legitimate user will ever hit. DO consider a highly secure application flow for password resetting and enable the user to configure it according to their preferences. This is a process unique to every project, so we can’t tell you how to solve the problem. Nevertheless here are a few good links:
加密(Cryptography)
¥Cryptography
不要创建自己的加密解决方案
¥DON’T create your own cryptographic solution
不要以明文形式存储个人信息
¥DON’T store personal information in plaintext
不要创建自己的加密解决方案(故意重复)
¥DON’T create your own cryptographic solution (intentionally repeating it)
不要忽略任何实现细节
¥DON’T ignore any aspect of implementation details
不要创建自己的加密解决方案(故意重复)
¥DON’T create your own cryptographic solution (intentionally repeating it)
不要使用 MD5 或 SHA1
¥DON’T use MD5 or SHA1
请勿创建你的 自己的加密解决方案
¥DON’T create your own cryptographic solution
libsodium 是阅读此主题并正确选择工业级解决方案的好地方。
¥A great place to read about this topic and properly choose an industrial strength solution is libsodium
分布(Distribution)
¥Distribution
提示
如果有人想更改数据库中的某些内容或将某个文件添加到服务器,并且他们没有使用 SSH 密钥,请务必验证并清理输入。
¥If someone wants to change something in your database or add some file to the server and they are not using an SSH key, DO validate AND sanitize the input.
Web(Web)
请勿使用 http
¥DON’T use http
不要将敏感数据存储在 JWT 中
¥DON’T store sensitive data in JWT
请使用 https / wss
¥DO Use https / wss
务必手动审计你的证书
¥DO manually audit your certificates
请验证用户
¥DO validate users
请记住,JWT 并非按原样加密
¥DO remember that JWT isn’t encrypted per sé
请使用 JWE 代替 JWT,并使用 AES256 CBC + HMAC SHA512
¥DO use JWE instead of JWT and use AES256 CBC + HMAC SHA512
务必加倍努力并执行完整的 OWASP Web 审计
¥DO double-down and perform the complete OWASP web audit
Cordova / Capacitor(Cordova / Capacitor)
请勿使用 iframe
¥DON’T use iframes
不要为 Android Gingerbread 打包
¥DON’T package for Android Gingerbread
请签署你的所有构建版本
¥DO sign all your builds
务必加密所有静态数据
¥DO encrypt all data at rest
Cordova 文档页面 详细介绍了如何保护 Cordova,虽然它看起来有些过时,但大部分信息仍然适用。
¥The Cordova Docs Page goes into detail about securing Cordova, and although it seems outdated, the information is mostly still on point.
Electron(Electron)
Electron 是一个非常特殊的情况,因为 XSS 和远程代码注入实际上可能导致终端用户(甚至开发者)设备的完全入侵。
¥Electron is a very special case, because XSS and remote code injection can actually lead to complete compromise of the end-user’s (or even developer’s) device.
请勿禁用
websecurity
¥DON’T disable
websecurity
不要启用远程代码执行
¥DON’T enable remote code execution
务必阅读我们关于增强型 Electron 安全 的指南。
¥DO read our guidelines for enhanced Electron Safety.
SSR(SSR)
当你使用 SSR 模式生成项目时,你将获得一个精简的 Express 服务器。你有责任强化你的环境以保护你的服务器和用户。为此,我们提供了一系列重要的标头,你可以考虑并在项目进入生产阶段之前有选择地激活它们(参见 src-ssr/index.js
)。请务必记住,HEADERS 并非万无一失,因为浏览器厂商会自行决定是否遵守这些规则。 - 例如,如果你的内容安全策略使用 sandbox
值,则使用 Chrome 将无法使用 PDF 查看。
¥When you generate your project with the SSR mode, you are provided with a minimal Express server. It is your responsibility to harden your environment to protect your server and your users. To this end, we have provided a collection of important HEADERS that you can consider and should selectively activate before your project enters the production phase (see src-ssr/index.js
). It is important to remember, that HEADERS are not bulletproof, because it is up to Browser vendors to respect them - and for example Chrome will break PDF viewing if your Content Security Policy uses the sandbox
value.
不要忘记设置限制性标头
¥DON’T forget to set restrictive headers
不要认为仅靠标头就能保护你免受所有攻击
¥DON’T think that headers alone will protect you from all attacks
请阅读 headers 的相关内容
¥DO read about headers
环境安全(Environmental Safety)
¥Environmental Safety
更安全意味着要考虑很多因素,你遵循的以下准则越多,受到攻击的痕迹就越小。
¥Being more safe means taking many things into consideration, and the more of the following guidelines you respect, the smaller the attack footprint will be.
操作安全性(Operational Security)
¥Operational Security
审核你的开发系统如何工作:
¥Audit how your development systems work:
请勿保留不需要的软件
¥DON’T retain unneeded software
请使用占用空间较小且启用安全功能的操作系统和发行版(例如 SELinux)
¥DO use an OS and distro with a smaller footprint and security features enabled (like SELinux for example)
务必确保你计算机上的所有软件都已更新(尤其是 NODE 系统)
¥DO make sure ALL software on your machine is up to date (especially NODE)
请使用密码管理器
¥DO use a password manager
请尽可能使用双因素身份验证 (2FA)
¥DO Use 2FA everywhere possible
审核你的生产环境如何工作:
¥Audit how your production environment works:
不要认为通过隐蔽性实现的安全性会在你受到攻击时有所帮助
¥DON’T think security through obscurity will help you when you are under attack
不要开放不必要的端口
¥DON’T leave unneeded ports open
不要假装容器或虚拟机本身就能保证你的安全
¥DON’T pretend containers or VM’s keep you safe by their nature
永远不要停止疑神疑鬼
¥DON’T ever stop being paranoid
请关闭服务器的密码和 root 访问权限
¥DO turn off password and root access to your server
请使用安全传输协议(SSH、HTTPS、SFTP、WSS)
¥DO use secure transfer protocols (SSH, HTTPS, SFTP, WSS)
务必安装 fail2ban 和 rkhunter
¥DO install fail2ban and rkhunter
请定期分析你的日志
¥DO regularly analyze your logs
务必加密静态数据
¥DO encrypt data at rest
请使用高级媒体类型分析
¥DO use advanced media-type analysis
请使用 ClamAV 检测受感染文件
¥DO use ClamAV to detect infected files
请进行定期系统维护
¥DO undertake regular system maintenance
请从允许/可用类型中删除旧密码
¥DO remove old ciphers from permitted / available types
务必使用 CSP 标头保护用户
¥DO protect users with CSP headers
组织和存储库安全性(Organizational & Repository Security)
¥Organizational & Repository Security
这是每个团队都应该关注并认真考虑的事情。请考虑谁有权访问你的代码库、如何合并提交以及如何发布资源。以下是一些需要记住的要点:
¥This is something that every team should have on their radar and put some thought into. DO consider who has access to your repositories, how commits are merged and how assets are published. Here are some good things to remember:
不要将敏感数据放入源代码中
¥DON’T put sensitive data in your source code
不要忽略
yarn audit
或npm audit
报告¥DON’T ignore
yarn audit
ornpm audit
reports不要盲目依赖第三方服务
¥DON’T blindly rely on third-party services
请要求在合并到主分支之前进行审阅
¥DO require a review before merging to master
请要求审阅者/代码提交者使用双重身份验证 (2FA)
¥DO require 2FA for reviewers / code committers
请要求提交签名
¥DO require signed commits
请认真对待 GitHub 安全警告
¥DO take GitHub Security Warnings seriously
请进行深度代码审查
¥DO undertake deep code reviews
请审查关键的第三方库,尤其是那些需要处理真实文件的库
¥DO review critical third-party libraries, especially any working with real files
务必锁定关键库的版本
¥DO pin versions of critical libraries
请提交软件包锁定文件
¥DO commit package lock files
请将
.env
文件添加到你的.gitignore
中。¥DO Add
.env
files to your.gitignore
最后说明(Final Note)
¥Final Note
安全并非安心,而是需要警惕和意识的实际知识应用。不要认为你已经做得足够了。总有更多你可以尝试的,总有新的漏洞需要注意。但最大的安全威胁莫过于懒惰,所以请穿上户外鞋,向上滚动页面,阅读 关于 XSS 的 OWASP 链接。我们不会告诉任何人。
¥Security is not peace of mind, it is a practical application of knowledge that requires vigilance and awareness. DON’T stop being concerned about security and DON’T think you are doing enough. There is always more you can undertake, there are constantly new vulnerabilities to be aware of. But the biggest security threat of them all is laziness, so put your outside shoes on, scroll back up the page and DO read the OWASP link about XSS. We won’t tell anybody.