跳到主要内容

渲染进程里禁止出现什么代码?(安全意识考察)

考察点​

  • 从"写出功能"到"写不出漏洞"的安全红线意识
  • XSS → 提权链条的理解

参考答案​

1. 禁止清单​

(1)禁止直接 require Node/Electron 模块

// ❌ 绝对禁止(nodeIntegration 必须保持关闭)
const fs = require('fs');
const { shell } = require('electron');
const { exec } = require('child_process');

渲染进程一旦出现这类代码,说明 nodeIntegration 被打开了——页面任何 XSS 都直接变成系统级 RCE。

(2)禁止不可信数据进 HTML 渲染

// ❌ XSS 入口:IPC/网络/文件来的数据直接 innerHTML
element.innerHTML = await window.api.getTemplate();

// ❌ Vue 的 v-html / React 的 dangerouslySetInnerHTML 同理
<div v-html="remoteContent"></div>

桌面端 XSS 的危害远大于 Web(下一跳就是桥接 API),所以:

  • 默认按文本渲染(textContent)
  • 富文本必须渲染时用 DOMPurify 消毒
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(untrustedHtml); // 白名单过滤

(3)禁止 eval / new Function / 内联脚本

// ❌ 字符串变代码:XSS 放大器,也违反 CSP
eval(userInput);
new Function('return ' + data)();

CSP 应禁用 'unsafe-eval'(开发环境 HMR 除外,见 CSP 篇)。

(4)禁止在渲染进程拼 shell 命令

// ❌ 把用户输入拼进命令,经桥接发给主进程执行
window.api.runCommand(`convert ${userFileName} output.png`);
// userFileName = "a.png; rm -rf ~" → 命令注入

正确:主进程用 execFile 数组传参 + 参数白名单校验,渲染进程只传语义化参数。

(5)禁止把敏感凭据长期放渲染侧

// ❌ localStorage 存长期 token/密钥(XSS 可读一切 storage)
localStorage.setItem('masterToken', token);

原则:渲染进程持有的凭据生命周期越短越好;刷新令牌等高价值凭据放主进程(keytar 系统钥匙串),渲染侧只持短期 access token。

(6)禁止加载不可信远程内容到特权上下文

// ❌ 主框架直接加载第三方 URL(该窗口有桥接 API)
location.href = 'https://untrusted-third-party.com';

远程内容用独立窗口 + 无 preload 配置加载(见「加载远程 URL 防 XSS」)。

2. 为什么渲染进程是"重点怀疑对象"​

攻击链条:
远程内容/用户输入 → XSS → 调用桥接 API → 主进程特权能力 → 系统沦陷
↑
渲染进程是这条链唯一能被攻击者直接触碰的环节

所以代码评审时对渲染进程代码的安全假设是:这里的任何输入都可能是恶意构造的,这里的任何代码都可能被篡改执行。

3. 团队落地手段​

  1. ESLint 规则拦截:
// .eslintrc 渲染进程目录的规则
{
rules: {
'no-restricted-globals': ['error', 'require'],
'no-eval': 'error',
'no-implied-eval': 'error',
}
}
  1. CSP 防线:script-src 'self' 让内联脚本根本执行不了
  2. code review 清单:搜 innerHTML、v-html、dangerouslySetInnerHTML、eval 逐一确认
  3. 依赖治理:渲染进程的 npm 依赖也要审计(供应链投毒最终也在渲染进程落地)

面试话术​

六条红线:不 require Node(nodeIntegration 保持关闭)、不可信数据不进 HTML(DOMPurify 兜底)、禁 eval 系(配合 CSP)、不拼 shell(参数化 + 主进程白名单)、高价值凭据不留渲染侧(keytar 放主进程)、远程内容不进特权窗口。核心认知:渲染进程是攻击链上唯一能被直接触碰的环节,按"输入皆恶意、代码皆可被篡改"假设来写。

常见追问​

  • 业务必须渲染富文本(如 markdown)怎么办? 服务端/主进程侧消毒 + 前端 DOMPurify 双保险,渲染在 sandboxed iframe 中进一步隔离。
  • localStorage 完全不能用吗? 存偏好设置可以,存凭据不行;敏感态数据考虑 sessionStorage(关窗即清)或主进程保管。