关于 security
面向应用代码安全审查与修复的技能,涵盖 CDF 访问、凭据、DOM、身份验证、输入校验、配置和依赖项。它按步骤指导审计,并要求汇报未能自动修复的问题。
主要功能
- 01梳理路由和数据入口
- 02将原始 CDF 请求迁移至 Cognite SDK
- 03检查密钥与不安全 DOM 模式
- 04审查身份验证和输入校验
- 05检查 Vite 配置与依赖项
- 06汇总修复内容和遗留问题
适用场景
- 01部署前审计应用
- 02查找并修复原始 CDF 网络请求
- 03审查凭据、身份验证和用户输入
- 04检查安全标头与依赖漏洞
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cognitedata/ builder-skills --skill security安装后在 Claude Code 中输入/security确认已加载。
详细介绍
安全修复
查找并修复 $ARGUMENTS 中的安全问题(如果未提供参数,则检查整个应用)。请按顺序完成以下每个步骤。任何步骤中发现的问题都必须一并修复。
步骤 1 — 梳理攻击面
在检查任何内容之前,先阅读以下文件:
src/main.tsx/src/App.tsx— 入口点、路由、身份验证门控vite.config.ts— 开发服务器代理、CORS、标头package.json— 第三方依赖项列表- 所有匹配
**/auth*、**/login*、**/token*、**/credential*的文件
识别:
- 所有页面/路由,以及每个页面/路由是否受身份验证保护
- 所有外部数据进入应用的位置(CDF SDK 调用、
fetch、用户表单输入) - 所有数据写回的位置(CDF upsert、
fetchPOST/PUT/DELETE)
步骤 2 — 将所有 CDF 访问迁移到 Cognite SDK
所有与 Cognite Data Fusion(CDF) 通信的流量都必须通过官方 Cognite SDK。查找任何绕过 SDK、访问类似 CDF 的主机或 API 的 HTTP、WebSocket 或其他网络调用,并将其改写为使用 SDK。
搜索原始 HTTP 调用
# Find fetch, axios, XMLHttpRequest, and other HTTP client usage
grep -rn --include="*.ts" --include="*.tsx" --include="*.js" \
-E "(fetch\(|axios\.|axios\(|XMLHttpRequest|\.ajax\(|http\.get\(|http\.post\(|request\()" src/
# Find raw URL construction that looks like CDF endpoints
grep -rn --include="*.ts" --include="*.tsx" \
-E "(cognitedata\.com|cognite\.ai|/api/v1/projects|cdf\.|\.cognite\.)" src/
# Find custom Authorization or api-key headers
grep -rn --include="*.ts" --include="*.tsx" \
-E "(Authorization|api-key|apikey|x-api-key)" src/ | grep -v "node_modules"
修复方法
对于找到的每个原始 CDF 调用,阅读周边代码以了解其目标 CDF 资源和操作,然后使用适当的 SDK 方法将其改写。若不再使用原始 HTTP 客户端导入,则将其移除。
| 模式 | 操作 |
|---|---|
对 CDF URL(*.cognitedata.com、/api/v1/projects/*)调用 fetch() 或 axios | 改写为使用 Cognite SDK(cognite.files.getDownloadUrls(...)、cognite.timeseries.retrieve(...)、client.instances.search(...) 等) |
使用自定义 Authorization 标头携带 CDF 令牌 | 移除 — SDK 会自动处理身份验证 |
| 与 CDF 端点建立 WebSocket 连接 | 改写为使用 SDK 流式传输方法 |
| 将请求转发至 CDF 的代理端点 | 改写代理,使其内部使用 SDK |
对非 CDF URL(静态资源、文档记录的第三方 API)调用 fetch() | 保留 — 但需添加注释说明其用途 |
改写所有 CDF 调用后,移除不再使用的任何 axios 或与 fetch 相关的导入。
可接受的情况
- 所有 CDF 读写均通过
sdk.files.*、sdk.timeseries.*、client.instances.*等完成。 - 非 CDF 网络调用符合以下情况:
- 访问已知的静态资源主机(CDN、图像服务)
- 访问产品所需且有文档说明的第三方 API
- 应用的 README 或架构文档中明确注明
步骤 3 — 检查并修复凭据与密钥管理
搜索硬编码的凭据和敏感值:
# Look for anything that smells like a secret in source files
grep -rn --include="*.ts" --include="*.tsx" --include="*.js" \
-E "(password|secret|apikey|api_key|token|bearer|private_key)\s*=\s*['\"]" src/
对于每个硬编码的密钥,将其替换为环境变量。创建或更新 .env.example,并在其中添加占位值。如果缺少 .env,则将其添加到 .gitignore。
修复方法
-
替换每个硬编码的密钥,改用
import.meta.env.VITE_*引用。例如:const apiKey = "sk-abc123"→const apiKey = import.meta.env.VITE_API_KEYconst token = "eyJhbG..."→const token = import.meta.env.VITE_AUTH_TOKEN
-
将变量添加到
.env.example,并设置占位值(例如VITE_API_KEY=your-api-key-here)。如果.env.example不存在,则创建它。 -
确保
.env和.env.local均已列入.gitignore— 缺少时请添加。 -
移除所有会打印 CDF 令牌、用户对象或 API 密钥的
console.log、console.error或类似调用。
步骤 4 — 检查并修复危险的 DOM API
搜索可能导致任意脚本执行或 HTML 注入的模式:
grep -rn --include="*.tsx" --include="*.ts" \
-E "dangerouslySetInnerHTML|innerHTML\s*=|eval\(|new Function\(|setTimeout\(['\"]|setInterval\(['\"]" src/
对于每个危险的 DOM 模式,直接应用修复。如有需要,使用 pnpm add dompurify 和 pnpm add -D @types/dompurify 安装 DOMPurify。
如何修复
-
dangerouslySetInnerHTML:使用DOMPurify.sanitize()包装该值。在文件中添加import DOMPurify from 'dompurify'。示例:// Before <div dangerouslySetInnerHTML={{ __html: userContent }} /> // After import DOMPurify from 'dompurify'; <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userContent) }} /> -
eval()/new Function():改用数据驱动的方式。使用JSON.parse()解析数据,或使用查找表 / switch 语句动态分发逻辑。切勿将用户可控的字符串传递给代码求值函数。 -
使用字符串参数的
setTimeout/setInterval:改为传入函数引用:// Before setTimeout("doSomething()", 1000) // After setTimeout(() => doSomething(), 1000)
第 5 步 — 查找并修复身份验证与授权漏洞
阅读身份验证设置(可能位于 src/contexts/、src/hooks/,或 setup-flows-auth 的输出中):
- 所有展示 CDF 数据的路由都必须受到 Flows 身份验证守卫的保护(渲染前,
useCogniteClient必须返回非 null 的sdk)。 - CDF 客户端必须使用短期 OIDC 令牌初始化,而不是静态 API 密钥。
- 用户角色 / 能力检查必须在服务端进行(CDF ACL);不得仅依靠隐藏 UI 元素。
检查 Atlas / agent:
- 优先使用 EOS 侧边栏(
integrate-fusion-agent);仅在例外情况下使用应用内的useAtlasChat agentExternalId不得来自用户输入;在执行 CDF 查询前验证工具 / 操作参数- 不得将 CDF 数据发送给第三方 LLM API;不得对查询结果进行不设上限的补全(5 / 最大 50,已缓存)
如何修复
对于每个展示 CDF 数据但未受保护的路由,使用身份验证守卫组件进行包装。例如,确保路由元素由一个检查 useCogniteClient 的组件包装,并在 SDK 尚未就绪时显示加载 / 登录状态。
对于 Atlas 工具的 execute 函数和 Fusion agent 操作处理程序,在每个函数开头添加参数验证。在任何 CDF 查询中使用 args 字段前,验证其类型符合预期且值处于预期范围内。
第 6 步 — 查找并修复输入验证漏洞
来自表单、URL 参数或查询字符串的所有值,在传递给 CDF 调用或渲染到 DOM 之前,都必须经过验证:
# Find useSearchParams, URLSearchParams, and form onChange handlers
grep -rn --include="*.tsx" --include="*.ts" \
-E "useSearchParams|URLSearchParams|searchParams\.get|e\.target\.value" src/
对每个未经验证的外部输入,添加运行时验证。如果尚未安装 Zod,请安装(pnpm add zod)。创建符合预期结构的 schema,并使用 .safeParse(),而不是类型断言。
如何修复
-
为 URL 参数和表单输入添加 Zod schema。示例:
import { z } from 'zod'; const paramSchema = z.object({ id: z.string().min(1), page: z.coerce.number().int().positive().default(1), }); const result = paramSchema.safeParse({ id: searchParams.get('id'), page: searchParams.get('page') }); if (!result.success) { /* handle error */ } -
将外部数据上的
as MyType类型断言替换为 Zod.safeParse()— 未经验证,绝不信任来自 URL 参数、表单输入或 API 响应的数据。 -
为
searchParams.get()添加空值回退处理 — 始终处理参数缺失或为空的情况。
第 7 步 — 查找并修复 Vite / 服务端配置
阅读 vite.config.ts 以及任何 server.ts / express.ts 文件。
如何修复
在 vite.config.ts 的 server.headers 部分添加缺失的安全标头。如果该部分不存在,则创建它。至少需要以下标头:
server: {
headers: {
'Content-Security-Policy': "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://*.cognitedata.com",
'X-Frame-Options': 'DENY',
'X-Content-Type-Options': 'nosniff',
},
}
调整 Content-Security-Policy,使其符合应用的实际需求(例如,为字体或图像添加特定的 CDN 主机)。
另外:
- 移除
vite.config.ts中将原始密钥嵌入构建包的所有define条目。改用import.meta.env。 - 确认开发代理(
server.proxy)不会在生产构建中暴露内部端点。
第 8 步 — 查找并修复依赖项漏洞
pnpm audit --audit-level=high
如何修复
- 先运行
pnpm audit fix,自动修复可处理的问题。 - 对于仍未修复的高危 / 严重 CVE,手动更新
package.json中的软件包版本,然后运行pnpm install。 - 如果存在漏洞的软件包没有可用的修复方案,请将其记录为已知风险,并检查是否有替代软件包。
第 9 步 — 报告剩余问题
仅报告无法自动修复的问题(例如,需要人工判断的架构决策、没有可用修复方案的软件包,或需要大幅重构的模式)。
总结每个步骤中修复的内容:
| 步骤 | 修复内容 | 剩余问题 |
|---|---|---|
| 2 — CDF SDK | 将 N 次原始调用迁移到 SDK | (任何无法迁移的问题) |
| 3 — 凭证 | 用环境变量替换 N 个硬编码密钥 | (任何需要人工决策的问题) |
| 4 — DOM | 清理 N 个危险模式 | (任何需要重构的问题) |
| 5 — 身份验证 | 为 N 个未受保护的路由添加包装 | (任何架构方面的缺口) |
| 6 — 验证 | 为 N 个输入添加 Zod 模式 | (任何需要自定义逻辑的问题) |
| 7 — Vite 配置 | 添加 N 个安全标头 | (任何需要调整 CSP 的问题) |
| 8 — 依赖项 | 修复 N 个存在漏洞的软件包 | (任何没有可用修复方案的软件包) |
如果任何剩余问题需要在部署前立即处理,请明确列出。
完成
说明修复了哪些问题,并确认应用的安全性有所提升。列出下次部署前需要人工判断的任何剩余事项。