From 65068df5dddb4220f7a52e828a13cbc4c0c71f88 Mon Sep 17 00:00:00 2001
From: Abner <22141172+Silentely@users.noreply.github.com>
Date: Sat, 13 Dec 2025 23:36:44 +0800
Subject: [PATCH] =?UTF-8?q?fix(sentry):=20=E4=BF=AE=E5=A4=8D=20CSP=20?=
=?UTF-8?q?=E5=86=85=E8=81=94=E8=84=9A=E6=9C=AC=E9=97=AE=E9=A2=98=E5=B9=B6?=
=?UTF-8?q?=E5=A2=9E=E5=BC=BA=E6=95=8F=E6=84=9F=E6=95=B0=E6=8D=AE=E8=84=B1?=
=?UTF-8?q?=E6=95=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 sentry-config.js 外链脚本替代 HTML 内联配置
- 修改 HTML 文件引用外链脚本以符合 CSP 策略
- 重写 inject-sentry-config.js 仅处理配置文件
- 添加 sentry-sdk-loaded 事件触发,修复 SDK 超时覆盖问题
- 增强 beforeSend 脱敏逻辑,覆盖 query_string 和更多敏感参数
---
scripts/inject-sentry-config.js | 61 +++++++++++++-----------------
src/giffgaff/giffgaff_modular.html | 8 +---
src/js/sentry-config.js | 11 ++++++
src/js/sentry-loader.js | 36 +++++++++++++++++-
src/simyo/simyo_modular.html | 8 +---
5 files changed, 76 insertions(+), 48 deletions(-)
create mode 100644 src/js/sentry-config.js
diff --git a/scripts/inject-sentry-config.js b/scripts/inject-sentry-config.js
index 5fadab5..c517a76 100644
--- a/scripts/inject-sentry-config.js
+++ b/scripts/inject-sentry-config.js
@@ -2,7 +2,7 @@
/**
* Sentry 配置注入脚本
*
- * 在构建时将 Sentry 环境变量注入到 HTML 文件中
+ * 在构建时将 Sentry 环境变量注入到 sentry-config.js 文件中
* 用法:在 npm run build 中调用此脚本
*/
@@ -14,48 +14,39 @@ const SENTRY_ENVIRONMENT = process.env.SENTRY_ENVIRONMENT || 'production';
const SENTRY_RELEASE = process.env.SENTRY_RELEASE ||
(process.env.COMMIT_REF ? `esim-tools@${process.env.COMMIT_REF.slice(0, 7)}` : 'esim-tools@unknown');
-// 要处理的 HTML 文件列表
-const htmlFiles = [
- 'dist/index.html',
- 'dist/src/giffgaff/giffgaff_modular.html',
- 'dist/src/giffgaff/giffgaff_complete_esim.html',
- 'dist/src/simyo/simyo_modular.html',
-];
+// 要处理的配置文件(改为处理独立的 JS 配置文件,而非 HTML 内联脚本)
+const configFile = 'dist/src/js/sentry-config.js';
console.log('[Sentry Config] 开始注入配置...');
console.log(` DSN: ${SENTRY_DSN ? '已配置' : '未配置'}`);
console.log(` Environment: ${SENTRY_ENVIRONMENT}`);
console.log(` Release: ${SENTRY_RELEASE}`);
-let processedCount = 0;
+const fullPath = path.join(process.cwd(), configFile);
-htmlFiles.forEach(filePath => {
- const fullPath = path.join(process.cwd(), filePath);
+if (!fs.existsSync(fullPath)) {
+ console.error(` ✗ 错误: ${configFile} 不存在`);
+ console.log('[Sentry Config] 失败,请确保构建流程正确复制了 sentry-config.js');
+ process.exit(1);
+}
- if (!fs.existsSync(fullPath)) {
- console.log(` 跳过: ${filePath} (文件不存在)`);
- return;
- }
+let content = fs.readFileSync(fullPath, 'utf8');
- let content = fs.readFileSync(fullPath, 'utf8');
+// 替换配置占位符
+content = content.replace(
+ /window\.SENTRY_DSN\s*=\s*['"][^'"]*['"]/,
+ `window.SENTRY_DSN = '${SENTRY_DSN}'`
+);
+content = content.replace(
+ /window\.SENTRY_ENVIRONMENT\s*=\s*['"][^'"]*['"]/,
+ `window.SENTRY_ENVIRONMENT = '${SENTRY_ENVIRONMENT}'`
+);
+content = content.replace(
+ /window\.SENTRY_RELEASE\s*=\s*['"][^'"]*['"]/,
+ `window.SENTRY_RELEASE = '${SENTRY_RELEASE}'`
+);
- // 替换配置占位符
- content = content.replace(
- /window\.SENTRY_DSN\s*=\s*['"][^'"]*['"]/,
- `window.SENTRY_DSN = '${SENTRY_DSN}'`
- );
- content = content.replace(
- /window\.SENTRY_ENVIRONMENT\s*=\s*['"][^'"]*['"]/,
- `window.SENTRY_ENVIRONMENT = '${SENTRY_ENVIRONMENT}'`
- );
- content = content.replace(
- /window\.SENTRY_RELEASE\s*=\s*['"][^'"]*['"]/,
- `window.SENTRY_RELEASE = '${SENTRY_RELEASE}'`
- );
+fs.writeFileSync(fullPath, content, 'utf8');
+console.log(` ✓ 已处理: ${configFile}`);
- fs.writeFileSync(fullPath, content, 'utf8');
- console.log(` ✓ 已处理: ${filePath}`);
- processedCount++;
-});
-
-console.log(`[Sentry Config] 完成,共处理 ${processedCount} 个文件`);
+console.log('[Sentry Config] 完成');
diff --git a/src/giffgaff/giffgaff_modular.html b/src/giffgaff/giffgaff_modular.html
index 85a3aa3..14e8a79 100644
--- a/src/giffgaff/giffgaff_modular.html
+++ b/src/giffgaff/giffgaff_modular.html
@@ -7,12 +7,8 @@
-
+
+
diff --git a/src/js/sentry-config.js b/src/js/sentry-config.js
new file mode 100644
index 0000000..9241738
--- /dev/null
+++ b/src/js/sentry-config.js
@@ -0,0 +1,11 @@
+/**
+ * Sentry 配置文件
+ *
+ * 此文件用于设置 Sentry 配置变量,在构建时由 inject-sentry-config.js 注入实际值
+ * 使用外链脚本而非内联脚本,以符合 CSP 策略
+ */
+
+// Sentry 配置 - 构建时会被注入实际值
+window.SENTRY_DSN = '';
+window.SENTRY_ENVIRONMENT = 'production';
+window.SENTRY_RELEASE = 'esim-tools@unknown';
diff --git a/src/js/sentry-loader.js b/src/js/sentry-loader.js
index 0d70605..2a987bf 100644
--- a/src/js/sentry-loader.js
+++ b/src/js/sentry-loader.js
@@ -113,7 +113,35 @@
// 敏感数据过滤
beforeSend: function(event) {
+ // 脱敏 URL 中的敏感查询参数
+ function sanitizeQueryString(url) {
+ if (!url) return url;
+ var sensitiveParams = ['token', 'key', 'password', 'code', 'state', 'access_token', 'refresh_token', 'auth', 'secret'];
+ try {
+ var urlObj = new URL(url, window.location.origin);
+ sensitiveParams.forEach(function(param) {
+ if (urlObj.searchParams.has(param)) {
+ urlObj.searchParams.set(param, '***');
+ }
+ });
+ return urlObj.toString();
+ } catch (e) {
+ // URL 解析失败,使用正则替换
+ return url.replace(/([?&])(token|key|password|code|state|access_token|refresh_token|auth|secret)=[^&]*/gi, '$1$2=***');
+ }
+ }
+
if (event.request) {
+ // 脱敏 query_string
+ if (event.request.query_string) {
+ event.request.query_string = event.request.query_string
+ .replace(/(token|key|password|code|state|access_token|refresh_token|auth|secret)=[^&]*/gi, '$1=***');
+ }
+ // 脱敏 URL
+ if (event.request.url) {
+ event.request.url = sanitizeQueryString(event.request.url);
+ }
+ // 删除敏感 cookies 和 headers
delete event.request.cookies;
if (event.request.headers) {
delete event.request.headers['authorization'];
@@ -129,7 +157,11 @@
.replace(/token[=:]\s*[^\s,]+/gi, 'token=***')
.replace(/key[=:]\s*[^\s,]+/gi, 'key=***')
.replace(/password[=:]\s*[^\s,]+/gi, 'password=***')
- .replace(/cookie[=:]\s*[^\s,]+/gi, 'cookie=***');
+ .replace(/cookie[=:]\s*[^\s,]+/gi, 'cookie=***')
+ .replace(/code[=:]\s*[^\s,]+/gi, 'code=***')
+ .replace(/state[=:]\s*[^\s,]+/gi, 'state=***')
+ .replace(/access_token[=:]\s*[^\s,]+/gi, 'access_token=***')
+ .replace(/refresh_token[=:]\s*[^\s,]+/gi, 'refresh_token=***');
}
});
}
@@ -200,6 +232,8 @@
console.log('[Sentry Loader] SDK 加载成功');
// 加载成功后立即初始化
initSentry();
+ // 触发自定义事件,通知其他模块 SDK 已加载
+ window.dispatchEvent(new Event('sentry-sdk-loaded'));
};
script.onerror = function() {
diff --git a/src/simyo/simyo_modular.html b/src/simyo/simyo_modular.html
index e87aead..3556561 100644
--- a/src/simyo/simyo_modular.html
+++ b/src/simyo/simyo_modular.html
@@ -7,12 +7,8 @@
-
+
+