You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native中安全运行不可信JavaScript代码?

在React Native中安全运行不可信代码的替代方案

1. 利用WebView实现沙箱隔离

React Native自带的WebView组件是天然的沙箱环境,不可信代码在WebView的独立上下文运行,无法直接访问RN主进程资源或API。

实现思路:

  • 在RN项目assets目录创建本地HTML文件,封装代码执行逻辑,通过postMessage与RN主进程通信。
  • RN端通过WebView的postMessage传递不可信代码,WebView执行后再通过postMessage返回结果。

示例代码:

本地HTML(assets/sandbox.html):

<!DOCTYPE html>
<html>
<body>
  <script>
    window.addEventListener('message', (event) => {
      const { code } = JSON.parse(event.data);
      try {
        const result = (() => {
          'use strict';
          return eval(code); // 仅在WebView沙箱内执行,不影响RN主进程
        })();
        window.ReactNativeWebView.postMessage(JSON.stringify({ success: true, result }));
      } catch (error) {
        window.ReactNativeWebView.postMessage(JSON.stringify({ success: false, error: error.message }));
      }
    });
  </script>
</body>
</html>

RN端组件:

import React, { useRef } from 'react';
import { WebView } from 'react-native-webview';

const CodeSandbox = () => {
  const webViewRef = useRef(null);

  const runUntrustedCode = (code) => {
    webViewRef.current?.postMessage(JSON.stringify({ code }));
  };

  const handleMessage = (event) => {
    const data = JSON.parse(event.nativeEvent.data);
    if (data.success) {
      console.log('执行结果:', data.result);
    } else {
      console.error('代码执行失败:', data.error);
    }
  };

  return (
    <WebView
      ref={webViewRef}
      source={require('./assets/sandbox.html')}
      onMessage={handleMessage}
      style={{ height: 0, width: 0 }} // 隐藏WebView
    />
  );
};

export default CodeSandbox;

优缺点:

  • ✅ 无需额外依赖,RN原生支持,沙箱隔离性强
  • ✅ 实现成本低,无需复杂配置
  • ❌ 代码执行和结果传递有通信开销,性能略逊于原生JS环境
  • ❌ WebView的JS环境与RN环境不一致,无法直接使用RN API

2. 基于Hermes引擎创建隔离上下文

如果你的RN项目使用Hermes作为JS引擎(默认开启),可利用Hermes内部API创建独立隔离上下文,限制不可信代码的全局访问权限。

实现思路:

  • 通过HermesInternal API创建全新上下文,手动注入仅允许的全局对象(如Math、JSON),避免暴露RN全局资源。
  • 在隔离上下文中执行不可信代码,捕获结果或错误。

示例代码:

import { HermesInternal } from 'hermes-engine';

const runInIsolatedContext = (untrustedCode) => {
  try {
    const isolatedCtx = HermesInternal.createContext();
    // 仅暴露安全全局对象,冻结防止篡改
    isolatedCtx.global = {
      Math: Object.freeze(Math),
      JSON: Object.freeze(JSON),
      console: { log: () => {} }, // 可选:限制日志输出
    };
    const result = HermesInternal.evaluateScriptInContext(
      untrustedCode,
      isolatedCtx,
      { filename: 'untrusted-code.js' }
    );
    return { success: true, result };
  } catch (error) {
    return { success: false, error: error.message };
  }
};

// 使用示例
const codeResult = runInIsolatedContext('Math.sqrt(16)');
console.log(codeResult);

优缺点:

  • ✅ 性能接近原生JS执行,无跨上下文通信开销
  • ✅ 可精确控制暴露的全局API,安全性高
  • ❌ 依赖Hermes内部API,存在版本兼容性风险(API可能随版本变更)
  • ❌ 需要手动处理上下文隔离细节,防止代码逃逸

3. 使用WebAssembly(Wasm)沙箱化执行

将不可信代码编译为WebAssembly模块,在RN中加载执行。Wasm本身具备严格的内存隔离机制,无法直接访问宿主环境资源。

实现思路:

  • 将不可信JS代码通过AssemblyScript编译为Wasm,或用Emscripten编译C/C++等语言为Wasm。
  • 在RN中通过WebAssembly API加载模块,调用暴露的执行方法获取结果。

示例代码(AssemblyScript编译Wasm):

  1. 编写AssemblyScript代码(src/index.ts):
export function runCode(code: string): string {
  try {
    const result = eval(code); // 仅在Wasm环境内执行
    return JSON.stringify({ success: true, result });
  } catch (e) {
    return JSON.stringify({ success: false, error: (e as Error).message });
  }
}
  1. 编译为Wasm后,RN端加载:
const loadWasmSandbox = async () => {
  const response = await fetch(require('./assets/sandbox.wasm'));
  const bytes = await response.arrayBuffer();
  const { instance } = await WebAssembly.instantiate(bytes);
  return instance.exports.runCode as (code: string) => string;
};

// 使用示例
loadWasmSandbox().then(runCode => {
  const result = runCode('2 + 3');
  console.log(JSON.parse(result));
});

优缺点:

  • ✅ 沙箱隔离性极强,Wasm代码无法直接访问宿主环境
  • ✅ 执行性能高,适合计算密集型任务
  • ❌ 需要将不可信代码转换为Wasm,转换成本较高
  • ❌ 对动态JS代码的支持有限,需额外实现代码解析逻辑

4. 基于SES(Secure EcmaScript)创建安全执行环境

SES是TC39推出的安全ECMAScript沙箱库,通过冻结全局对象、限制代码权限实现安全执行,可尝试在RN环境适配使用。

实现思路:

  • 安装SES库,调用lockdown()冻结全局对象,创建Compartment隔离上下文。
  • 在Compartment中执行不可信代码,仅暴露允许的API。

示例代码:

import SES from 'ses';

// 初始化SES,冻结全局对象
SES.lockdown();

const runInSES = (untrustedCode) => {
  try {
    const compartment = new SES.Compartment({
      Math: Math,
      JSON: JSON,
    });
    const result = compartment.evaluate(untrustedCode);
    return { success: true, result };
  } catch (error) {
    return { success: false, error: error.message };
  }
};

// 使用示例
const result = runInSES('Math.pow(2, 3)');
console.log(result);

优缺点:

  • ✅ 基于标准规范,安全性经过验证
  • ✅ 可灵活配置允许的全局API
  • ❌ RN环境可能存在兼容性问题,需测试适配
  • ❌ 对某些RN特有全局对象的处理需要额外配置

内容的提问来源于stack exchange,提问作者john-salib

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:42:15