文章

AI Coding:ScriptCat的CSP功能(Trae Solo)

背景

chrome新版会根据响应头开启更加严格模式,CSP:

Content Security Policy of your site blocks the use of 'eval' in JavaScript`
The Content Security Policy (CSP) prevents the evaluation of arbitrary strings as JavaScript to make it more difficult for an attacker to inject unathorized code on your site.

To solve this issue, avoid using eval(), new Function(), setTimeout([string], ...) and setInterval([string], ...) for evaluating strings.

If you absolutely must: you can enable string evaluation by adding unsafe-eval as an allowed source in a script-src directive.

⚠️ Allowing string evaluation comes at the risk of inline script injection.

Trae Solo活动

【Trae】您好,恭喜您通过 TRAE × 脉脉「AI无限职场」SOLO 挑战赛报名审核!
您的 SOLO 内测权限已开通,可前往 TRAE 中国版官网(www/trae/cn)下载SOLO桌面端(macOS 版),或访问 (www/solo/trae/cn)完成参赛作品创作,期待您的精彩呈现!作品提交入口与指南:https://forum.trae.cn/t/topic/4988/3

PR:

https://github.com/scriptscat/scriptcat/pull/1348

测试脚本

// ==UserScript==
// @name         GitHub 页面加载完成后打印日志
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  等待 GitHub 页面完全加载后再执行 console 日志
// @author       助手
// @match        https://github.com/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    console.log('=== CSP unsafe-eval 测试开始 ===');

    // 1. eval
    function testEval() {
        try {
            eval('console.log("eval 执行")');
        } catch (e) {
            console.error('eval 被 CSP 拦截:', e);
        }
    }

    // 2. new Function
    function testNewFunction() {
        try {
            const fn = new Function('console.log("new Function 执行")');
            fn();
        } catch (e) {
            console.error('new Function 被 CSP 拦截:', e);
        }
    }

    // 3. setTimeout 字符串
    function testSetTimeoutString() {
        try {
            setTimeout('console.log("setTimeout 字符串执行")', 100);
        } catch (e) {
            console.error('setTimeout 字符串被 CSP 拦截:', e);
        }
    }

    // 4. setInterval 字符串
    function testSetIntervalString() {
        try {
            setInterval('console.log("setInterval 字符串执行")', 1000);
        } catch (e) {
            console.error('setInterval 字符串被 CSP 拦截:', e);
        }
    }

    // 批量执行
    testEval();
    testNewFunction();
    testSetTimeoutString();
    testSetIntervalString();

    console.log('=== 测试完成 ===');
})();

技术方案

# ScriptCat 扩展功能开发提示词

你是 ScriptCat Chrome 扩展(Manifest V3)的开发专家。项目基于 React + TypeScript + Arco Design,使用 pnpm 管理依赖。

## 架构模式

项目采用 **Service/Client/Repo 三层架构**:

- **Repo(数据层)**:继承 `Repo<T>` 基类(位于 `src/app/repo/repo.ts`),使用 `chrome.storage.local` 持久化。**禁止使用 localStorage**(Service Worker 不支持)。
- **Service(服务层)**:继承 `Group` API 注册 Message Handler(位于 `src/app/service/service_worker/`),处理业务逻辑。
- **Client(客户端层)**:继承 `Client` 基类(位于 `src/app/service/service_worker/client.ts`),封装跨层消息调用供 UI 使用。
- **注册入口**:在 `src/app/service/service_worker/index.ts` 中实例化并注册回调。

## 跨层通信

- **直接回调**:Service 通过 `setOnXxxChanged(callback)` 暴露回调,在 index.ts 中绑定到拦截器/处理器,确保规则变更时立即生效(不依赖消息队列时序)。
- **消息队列**:同时通过 `mq.publish()` 发布事件,供其他监听者使用。
- **优先使用直接回调**处理需要实时响应的场景(如 DNR 规则更新)。

## UI 规范

- 组件库:**Arco Design**(`@arco-design/web-react`)
- 国际化:`react-i18next`,翻译文件在 `src/locales/zh-CN/translation.json` 和 `en-US/translation.json`
- 页面路由:在 `src/pages/components/layout/Sider.tsx` 注册菜单和路由
- 弹窗互斥:Modal 和 Drawer 不可同时打开,打开一个自动关闭另一个
- 权限声明:如需新权限,在 `src/manifest.json` 的 `permissions` 或 `optional_permissions` 中添加

## 测试

- 框架:**vitest**
- 测试文件放在 `tests/` 目录下,与源码结构对应
- 运行:`npx vitest run <test-file>`

## 提交规范

- 单个功能合并为一次 commit,commit message 包含完整功能点描述
- 提交前会自动执行 `tsc --noEmit && eslint --fix .`(pre-commit hook)
- ESLint 警告可忽略,错误必须修复

## 注意事项

- Service Worker 中没有 `localStorage`、`document`、`window` 等 DOM API
- Chrome DNR 规则 priority 必须 >= 1
- DNR 动态规则上限 5000 条,ID 建议从 10000 起始避免冲突
- JSDoc 注释中避免使用 `**`、`*/` 等 Markdown 语法(esbuild 会解析错误),用反引号包裹

我需要扩展当期插件支持CSP配置,支持规则维度,支持全局开关,并且规则配置遵循:https://wproxy.org/docs/rules/pattern.html