Add files via upload

This commit is contained in:
公明
2026-07-16 11:30:34 +08:00
committed by GitHub
parent b39fefd2d0
commit 64abe12889
7 changed files with 64 additions and 31 deletions
@@ -1,6 +1,6 @@
## CyberStrikeAI Browser Extension
**Version 0.3.8** — Full docs: **README.zh-CN.md**
**Version 0.3.10** — Full docs: **README.zh-CN.md**
Chromium DevTools extension: capture Network traffic and send it to CyberStrikeAI for AI-assisted security testing. Aligned with the Burp Suite plugin.
@@ -51,7 +51,7 @@ Closing DevTools clears panel data. Closing the browser invalidates the session
After reloading the extension, close DevTools completely and reopen (F12) if you see `chrome.runtime.connect` errors — the old panel context is invalidated.
If Validate reports `cross-origin request denied`, upgrade and restart the CyberStrikeAI server. Current versions recognize valid Chrome/Edge extension origins automatically, so no extension ID or CORS configuration is required. The browser will still request host access on the first Validate.
If Validate reports `cross-origin request denied`, upgrade and restart the CyberStrikeAI server. Current versions recognize valid Chrome/Edge extension origins automatically, so no extension ID or CORS configuration is required. The browser requests access only to the configured server origin on the first Validate, directly from the Validate click so Chromium can reliably show the optional-permission prompt.
### Package
@@ -1,6 +1,6 @@
## CyberStrikeAI 浏览器扩展
**当前版本:0.3.8**UI 为英文;中文说明见下文)
**当前版本:0.3.10**UI 为英文;中文说明见下文)
Chrome / EdgeChromiumDevTools 扩展:在开发者工具中捕获 **Network** 流量,发送到 CyberStrikeAI 进行 AI 辅助安全测试。能力与 Burp Suite 插件对齐,并按生产场景做了性能与体验优化。
@@ -88,6 +88,7 @@ Cookie: ...
- **401/403** 时自动清空 Token 并展开连接栏
- Send 前主动校验 Token 有效性
- **optional_host_permissions**Validate 时按需授权
- 权限申请直接绑定 Validate 点击事件,仅申请当前 CyberStrikeAI 服务 origin;已授权地址不会重复弹窗
---
@@ -161,6 +162,12 @@ HTTP/2 伪首部。展示与 AI Prompt 已归一化为 HTTP/1.1;原始 HAR 仍
**Validate 显示 `cross-origin request denied`**
升级并重启 CyberStrikeAI 服务。新版服务会自动识别格式合法的 Chrome/Edge 扩展 Origin,无需复制插件 ID 或配置 CORS 白名单;插件首次 Validate 时仍会请求访问目标服务地址的浏览器权限。
**Validate 要求允许访问 CyberStrikeAI 服务?**
在浏览器弹出的权限框中允许访问当前服务地址。插件只按需申请所填写的服务 origin,不需要开启全站访问。如果未出现权限框,请在 `chrome://extensions/` 重新加载扩展,完全关闭 DevTools 后再打开并点击 Validate。
**HTTPS 显示无法连接,但 Burp 正常?**
Burp 插件会信任自签名证书,浏览器扩展不能绕过 Chromium 的 TLS 校验。请先在浏览器中打开服务地址并信任证书;生产环境建议使用包含服务 IP/域名 SAN 的受信任证书。
**Test History 很多会挡住 Captured Requests 吗?**
不会。历史区最高占侧边栏 **42%**,超出部分区域内滚动;捕获区占剩余空间。
@@ -14,8 +14,14 @@ async function apiFetch(baseUrl, path, options = {}) {
try {
res = await fetch(baseUrl + path, options);
} catch (err) {
const e = err instanceof Error ? err : new Error(String(err));
if (err && err.name === 'AbortError') throw err;
const detail = err instanceof Error ? err.message : String(err);
const e = new Error(
`Cannot reach ${baseUrl}. Check network/CORS and trust the HTTPS certificate in this browser` +
(detail ? ` (${detail})` : '')
);
e.network = true;
e.cause = err;
throw e;
}
const text = await res.text();
@@ -175,20 +175,30 @@ function baseUrlFrom(cfg) {
return `${scheme}://${cfg.host}:${cfg.port}`;
}
/** Request optional host permission for the configured CyberStrikeAI origin. */
async function ensureHostPermission(baseUrl) {
/**
* Request optional host permission for the configured CyberStrikeAI origin.
*
* Keep chrome.permissions.request() synchronous with the caller's click event.
* Awaiting permissions.contains() first can consume Chrome's transient user
* activation and make the request fail without showing a permission prompt.
*/
function ensureHostPermission(baseUrl) {
if (!extensionContextAlive()) throw extensionContextError();
if (!chrome.permissions || !chrome.permissions.request) return;
if (!chrome.permissions || !chrome.permissions.request) return Promise.resolve();
let origin;
try {
origin = new URL(baseUrl).origin + '/*';
} catch (_) {
throw new Error('Invalid Host/Port');
}
const has = await chrome.permissions.contains({ origins: [origin] });
if (has) return;
const granted = await chrome.permissions.request({ origins: [origin] });
if (!granted) {
throw new Error('Permission required to access the CyberStrikeAI server');
}
// Do not add an await before this call. Chrome requires a user gesture for
// optional permission requests. Requesting an already granted origin is
// idempotent and resolves true without prompting again.
return chrome.permissions.request({ origins: [origin] }).then((granted) => {
if (granted) return;
const err = new Error(`Allow extension access to ${new URL(baseUrl).origin} to continue`);
err.code = 'HOST_PERMISSION_DENIED';
throw err;
});
}
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "CyberStrikeAI",
"version": "0.3.9",
"version": "0.3.10",
"description": "Capture browser HTTP traffic and send to CyberStrikeAI for AI-assisted security testing.",
"devtools_page": "devtools.html",
"permissions": ["storage"],
@@ -678,19 +678,23 @@ async function initConfig() {
async function persistConnection() {
try {
await saveConfig({
host: $('host').value.trim(),
port: $('port').value.trim(),
https: $('https').checked,
filterApiOnly: $('filter-api').checked,
renderMarkdown: $('render-md').checked,
showDebugEvents: $('debug-events').checked,
});
await saveConfig(connectionConfigFromForm());
} catch (err) {
onContextLoss(err);
}
}
function connectionConfigFromForm() {
return {
host: $('host').value.trim(),
port: $('port').value.trim(),
https: $('https').checked,
filterApiOnly: $('filter-api').checked,
renderMarkdown: $('render-md').checked,
showDebugEvents: $('debug-events').checked,
};
}
async function onValidate() {
if (validating) {
validateAbort?.abort();
@@ -703,17 +707,23 @@ async function onValidate() {
validateAbort = new AbortController();
$('btn-validate').textContent = 'Cancel';
setStatus('Validating...', 'pending');
await persistConnection();
try {
config = await loadConfig();
} catch (err) {
if (onContextLoss(err)) return;
throw err;
}
const baseUrl = baseUrlFrom(config);
const nextConfig = connectionConfigFromForm();
const baseUrl = baseUrlFrom(nextConfig);
const password = $('password').value;
let hostPermission;
try {
await ensureHostPermission(baseUrl);
// Invoke before the first await so Chrome still associates the optional
// permission prompt with the Validate button's user gesture.
hostPermission = ensureHostPermission(baseUrl);
} catch (err) {
hostPermission = Promise.reject(err);
}
try {
await hostPermission;
await saveConfig(nextConfig);
config = { ...config, ...nextConfig };
const auth = await loginAndValidate(baseUrl, password, validateAbort.signal);
token = auth.token;
tokenExpiresAt = auth.expiresAt || '';