1o1swapnil/ShieldAI

GitHub: 1o1swapnil/ShieldAI

ShieldAI 是一个企业级 Shadow AI 治理平台,通过浏览器扩展、ML 分类器和完整的认证授权体系,帮助企业发现、监控并管理员工未经授权使用的 AI 工具。

Stars: 0 | Forks: 0

# ShieldAI [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/1o1swapnil/ShieldAI/actions/workflows/ci.yml) Shadow AI 治理平台。实现了 v1.1 设计补充协议: - **第 1 部分** — 诚实地重构覆盖率地图、原生应用流量出口(egress)检测、SSO OAuth 授权发现 - **第 2 部分** — 未知 AI 工具分类器(特征提取 + 审查队列) - **第 3 部分** — 扩展权限收紧、信任/安全摘要、签名构建验证 - **第 4 部分** — 员工监控通知/同意、基于司法管辖区的功能开关 同时包含了补充协议中默认已存在的 v1.0 基础组件: - 活动事件摄取 pipeline(第 8 部分),扩展的内容脚本(content script)为其提供数据,分类器的聚合使用信号现在也从中读取数据 - 真正的 AI 工具库(第 12 部分):涵盖 15 个类别的 150 多个预置工具,取代了原有的 `ai_tools` 存根 - 真正的认证 + SSO(第 6-7 部分):密码登录、JWT 会话、通用的 OIDC 连接器(Okta/Azure AD/任何兼容的 IdP),以及在管理后台每个路由上的组织/角色授权 —— 取代了早期每个 endpoint 使用的“信任客户端发送的任何 org_id”模型 - 用于扩展自身摄取调用的设备令牌(device token)认证(第 7 部分):管理员签发的安装令牌(install token)一次性换取一个长期有效且可单独撤销的设备令牌,彻底堵住了最后存在的“信任客户端发送的任何 org_id/user_id”漏洞 - CORS,以及在账户或设备获得有效凭证之前进行电子邮件验证 —— 堵住了“输入任何电子邮件,即可绑定该身份”的身份漏洞 - 对 `/auth/login`(基于 IP 和电子邮件)和 `/auth/register`(基于 IP)进行速率限制 —— 堵住了暴露的暴力破解/撞库漏洞 - 用户会话 JWT 的撤销机制,类似于设备令牌模型:每次登录对应一条 `sessions` 记录,并在每次请求时进行实时检查,因此一旦会话泄露/被攻破,可以被立即终止,而不是等到其 24 小时的有效期自然结束 - 验证邮件发送服务背后的真实 SMTP 提供商(`nodemailer`),取代了仅在控制台输出日志的存根 ## 结构 ``` server/ Express + Postgres API web/ Vite + React admin/employee dashboard extension/ Manifest V3 browser extension ``` ## 前置条件 - Node.js 18+ - PostgreSQL(任何最新版本) ## 服务器 ``` cd server npm install cp .env.example .env # set DATABASE_URL to your Postgres instance ``` 创建数据库,然后按顺序应用迁移: ``` createdb shieldai psql -d shieldai -f migrations/0001_base.sql psql -d shieldai -f migrations/0002_consent.sql psql -d shieldai -f migrations/0003_extension_trust.sql psql -d shieldai -f migrations/0004_unverified_tools.sql psql -d shieldai -f migrations/0005_coverage.sql psql -d shieldai -f migrations/0006_activity_events.sql psql -d shieldai -f migrations/0007_ai_tools_library.sql psql -d shieldai -f migrations/0008_auth.sql psql -d shieldai -f migrations/0009_device_auth.sql psql -d shieldai -f migrations/0010_email_verification.sql psql -d shieldai -f migrations/0011_session_revocation.sql ``` 初始化 AI 工具库(幂等操作 —— 在种子列表扩大后重新运行也是安全的): ``` DATABASE_URL=... node seeds/seed-ai-tools.js ``` 运行测试并启动服务器: ``` npm test npm start # listens on PORT (default 3000) ``` 在生产环境中设置 `JWT_SECRET`(否则每次进程启动都会生成一个临时密钥 —— 这对本地开发没问题,但每次重启都会使会话失效)。对于 SSO,请设置 `OIDC_ISSUER_URL`、`OIDC_CLIENT_ID`、`OIDC_CLIENT_SECRET`、`OIDC_REDIRECT_URI`(适用于任何符合标准的 OIDC 提供商 —— Okta、Azure AD 等)以及 `WEB_ORIGIN`(同时用于 SSO 回调重定向和 CORS —— 请将其设置为 Web 应用的真实源;如果有多个请使用逗号分隔)。 `/auth/login` 和 `/auth/register` 受到基于 `req.ip`(单个 IP)的速率限制,对于登录,还会基于电子邮件进行限制。如果部署在真实的反向代理/负载均衡器之后,请在 `src/index.js` 中调用 `app.set('trust proxy', ...)` 并设置正确的跳数(hop count) —— 否则代理后的每个客户端都会共享 Express 的默认 IP(即代理自身的地址),这会导致基于单个 IP 的限制器失效,或者变成所有人共用的一个配额池。 电子邮件功能(`src/email.js`,通过 `nodemailer`):不设置 `SMTP_HOST`(默认情况)会将验证链接打印到 stdout 而不是发送出去 —— 本地开发/测试无需真实的邮箱。设置 `SMTP_HOST`、`SMTP_PORT`(默认为 587)、`SMTP_USER`、`SMTP_PASS`、`SMTP_FROM`,如果你的提供商使用隐式 TLS(端口 465)而不是 STARTTLS,则需设置 `SMTP_SECURE=true`,即可发送真实邮件 —— 适用于任何标准 SMTP 提供商(SES、SendGrid、Postmark 等)。注册是事务性的:如果电子邮件发送失败,组织/用户(或设备)的数据行将完全回滚,而不会留下卡住的半注册账户。 `0001_base.sql` 中的 `organizations`/`users` 存根后来增加了真实的认证字段(0008)—— 真正的 v1.0 基础 schema 的其余部分(例如正式的邀请流程)仍然不属于本补充协议的范畴。 部署 0011 迁移会强制所有人重新认证:现有的令牌缺少 `sid` 声明来匹配 `sessions` 记录,因此 `requireAuth` 会将它们正确地视为已撤销。与 0010 的数据回填不同,这里不需要进行任何过渡处理 —— 因为在此迁移之前会话是不存在的。 ## Web ``` cd web npm install npm run dev # dev server npm run build # production build to dist/ ``` 如果 API 不在本地运行,请设置 `VITE_API_BASE`(默认为 `http://localhost:3000`)。 首次加载时注册组织(或登录);组织 ID 来自你的会话 —— 不再需要手动粘贴。 ## 扩展 将 `extension/` 作为已解压的扩展程序加载(`chrome://extensions` → 开发者模式 → 加载已解压的扩展程序)。 管理员从“设备”选项卡(或 `POST /org/:orgId/install-tokens`)创建安装令牌,并与员工分享类似于 `chrome-extension:///notice.html?install_token=` 的链接。打开它会将该 令牌换取为长期有效的设备令牌(`POST /extension/register-device`),随后扩展在每次 面向设备的调用中都会使用它。在同一选项卡中撤销设备可立即切断其连接, 这与令牌本身的有效期无关。 API 的基础 URL 位于 `extension/config.json`(`{"apiBase": "..."}`)中,而不是源代码中的字面量 —— 只需编辑这一个文件 即可指向已部署的 API,无需更改 JS 或从源码重新构建。本地开发默认为 `http://localhost:3000`。 在打包发布之前,重新生成 service worker 自报告的构建哈希(包含 `config.json`,因此 如果 `config.json` 被篡改,也会像源文件被篡改一样被检测到): ``` node extension/build-hash.js ``` API 的 CORS 中间件(`server/src/cors.js`)始终允许 `chrome-extension://` 源,而不管 `WEB_ORIGIN` 的设置如何 —— 扩展的 id 并不是机密,且 bearer-token 认证意味着 CORS 并不是这些 调用的安全边界。已通过在无头 Chromium 中加载真实的已解压扩展进行了验证:`config.json` 能够正确解析 ,并且对 `GET /consent/notice` 的实时调用实现了端到端的成功。 ## 部署 ``` cp .env.example .env # set POSTGRES_PASSWORD, JWT_SECRET, WEB_ORIGIN, VITE_API_BASE docker compose up --build ``` 启动 Postgres、API(`localhost:3000`)和 Web 应用(`localhost:8080`)。服务器的 `docker-entrypoint.sh` 会在启动前运行 `scripts/migrate.js`(按顺序应用 `migrations/*.sql`,并在 `schema_migrations` 表中进行跟踪 —— 与上面手动的 `psql -f` 序列不同,它可以在每次容器启动时安全运行)和 `seeds/seed-ai-tools.js`,因此全新的环境无需手动操作即可准备就绪。数据在重启后 会持久化存储在 `postgres_data` 卷中。 `web/Dockerfile` 构建了 Vite 应用,并通过 nginx 提供服务,同时带有 SPA 回退配置(`nginx.conf`) —— 因为路由完全是通过查询参数在客户端处理的,而不是真实的路径,所以每个路径 (`/`、`/verify-email` 等)都会提供 `index.html`。 尚未构建的功能:TLS 终止、除了 `docker compose` 之外的进程管理器/编排器(例如 Kubernetes manifests),以及日志采集/监控 —— 这仅能让试点运行起来,而不是一个经过加固的生产级集群。 ## API 概览 | 路由 | 用途 | |---|---| | `POST /auth/register`, `POST /auth/login`, `POST /auth/verify-email`, `GET /auth/me`, `POST /auth/logout` | 密码认证 + JWT 会话 + 电子邮件验证(第 7 部分) | | `GET /auth/sso/login`, `GET /auth/sso/callback` | 通用的 OIDC SSO 登录 —— Okta/Azure AD/任何兼容的 IdP(第 6 部分) | | `GET /auth/sessions`, `POST /auth/sessions/:id/revoke` | 自助会话管理(“退出其他设备”) | | `POST/GET /org/:orgId/install-tokens`, `.../install-tokens/:id/revoke`, `GET /org/:orgId/devices`, `.../devices/:id/revoke` | 管理员签发的设备凭证(第 7 部分) | | `GET /org/:orgId/sessions`, `POST /org/:orgId/sessions/:id/revoke` | 管理员可以终止其组织内的任何会话 —— 用于应对笔记本电脑被盗/令牌泄露的安全事件 | | `POST /extension/register-device`, `POST /extension/verify-device`, `GET /extension/device-status` | 针对设备的安装令牌交换 + 电子邮件验证(新的/未经验证的电子邮件在点击邮件中的链接之前,只会获得一个轮询票据,而不是令牌) | | `GET/POST /consent/*` | 监控通知、确认、状态(第 4 部分) | | `GET/PATCH /org/:orgId/settings` | 司法管辖区、受控功能开关、DNS/代理标志 | | `GET /org/security-summary` | 数据保留/加密/子处理方摘要(第 3 部分) | | `POST /extension/config` | 扩展自报告版本/构建哈希 | | `GET /org/:orgId/extension-versions` | 每次安装的构建验证状态 | | `POST /tools/classify`, `GET/PATCH /tools/unverified` | 未知工具分类器 + 审查队列(第 2 部分) | | `GET /org/:orgId/coverage-map` | 特定组织的检测覆盖率状态(第 1 部分) | | `POST /native-app/detect` | 原生桌面应用流量出口(egress)检测 | | `POST /integrations/scan`, `GET/PATCH /integrations/discovered` | SSO OAuth 授权发现 | | `POST /activity/events`, `GET /activity/events`, `GET /activity/summary` | 真实的活动摄取 + 特定工具的使用汇总(第 8 部分) | | `GET /tools/library`, `POST /tools/library` | AI 工具库列表(可按类别/来源过滤) + 手动添加(第 12 部分 / 1.2) | 上述所有的管理后台路由都需要 `Authorization: Bearer `(用户会话),如果组织不匹配则返回 403 错误;`/tools/library` 需要来自任何组织的管理员(该库是共享的,而非特定于组织)。`POST /consent/acknowledge`、`GET /consent/status`、`POST /extension/config`、`POST /native-app/detect` 和 `POST /activity/events` 则需要 `Authorization: Bearer ` —— org_id/user_id 来自令牌,而不是请求体,并且用户会话中间件会拒绝设备令牌类型的 JWT,反之亦然。`POST /extension/register-device`(安装令牌交换)和 `GET /consent/notice` 是仅有的真正公开的、面向设备的路由。`GET /org/security-summary` 也是特意公开的(第 3.2 部分 —— 安全审查人员在成为客户之前就会提取该信息)。
标签:MITM代理, Shadow AI治理, 单点登录, 员工行为监控, 机器学习分类器, 测试用例, 浏览器扩展管理, 版权保护, 自定义脚本, 身份与访问管理