opencode-api-security-testing 4.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/package.json +48 -47
  2. package/postinstall.mjs +69 -40
  3. package/references/references/README.md +72 -0
  4. package/references/references/asset-discovery.md +119 -0
  5. package/references/references/fuzzing-patterns.md +129 -0
  6. package/references/references/graphql-guidance.md +108 -0
  7. package/references/references/intake.md +84 -0
  8. package/references/references/pua-agent.md +192 -0
  9. package/references/references/report-template.md +156 -0
  10. package/references/references/rest-guidance.md +76 -0
  11. package/references/references/severity-model.md +76 -0
  12. package/references/references/test-matrix.md +86 -0
  13. package/references/references/validation.md +78 -0
  14. package/references/references/vulnerabilities/01-sqli-tests.md +1128 -0
  15. package/references/references/vulnerabilities/02-user-enum-tests.md +423 -0
  16. package/references/references/vulnerabilities/03-jwt-tests.md +499 -0
  17. package/references/references/vulnerabilities/04-idor-tests.md +362 -0
  18. package/references/references/vulnerabilities/05-sensitive-data-tests.md +466 -0
  19. package/references/references/vulnerabilities/06-biz-logic-tests.md +501 -0
  20. package/references/references/vulnerabilities/07-security-config-tests.md +511 -0
  21. package/references/references/vulnerabilities/08-brute-force-tests.md +457 -0
  22. package/references/references/vulnerabilities/09-vulnerability-chains.md +465 -0
  23. package/references/references/vulnerabilities/10-auth-tests.md +537 -0
  24. package/references/references/vulnerabilities/11-graphql-tests.md +355 -0
  25. package/references/references/vulnerabilities/12-ssrf-tests.md +396 -0
  26. package/references/references/vulnerabilities/README.md +148 -0
  27. package/references/references/workflows.md +192 -0
  28. package/src/index.ts +153 -25
  29. package/src/src/index.ts +535 -0
package/package.json CHANGED
@@ -1,47 +1,48 @@
1
- {
2
- "name": "opencode-api-security-testing",
3
- "version": "4.0.1",
4
- "description": "API Security Testing Plugin for OpenCode - Automated vulnerability scanning and penetration testing",
5
- "type": "module",
6
- "main": "src/index.ts",
7
- "files": [
8
- "src/",
9
- "agents/",
10
- "core/",
11
- "references/",
12
- "SKILL.md",
13
- "postinstall.mjs",
14
- "preuninstall.mjs"
15
- ],
16
- "scripts": {
17
- "postinstall": "node postinstall.mjs",
18
- "preuninstall": "node preuninstall.mjs"
19
- },
20
- "keywords": [
21
- "opencode",
22
- "opencode-plugin",
23
- "security",
24
- "api-security",
25
- "pentest",
26
- "vulnerability-scanning"
27
- ],
28
- "author": "steveopen1",
29
- "license": "MIT",
30
- "repository": {
31
- "type": "git",
32
- "url": "https://github.com/steveopen1/skill-play"
33
- },
34
- "homepage": "https://github.com/steveopen1/skill-play/tree/main/agent-plugins/OPENCODE/api-security-testing",
35
- "peerDependencies": {
36
- "@opencode-ai/plugin": "^1.1.19",
37
- "@opencode-ai/sdk": "^1.1.19"
38
- },
39
- "dependencies": {
40
- "@opencode-ai/plugin": "^1.1.19",
41
- "@opencode-ai/sdk": "^1.1.19"
42
- },
43
- "devDependencies": {
44
- "@types/node": "^25.5.2",
45
- "typescript": "^6.0.2"
46
- }
47
- }
1
+ {
2
+ "name": "opencode-api-security-testing",
3
+ "version": "5.0.0",
4
+ "description": "API Security Testing Plugin for OpenCode - Automated vulnerability scanning and penetration testing",
5
+ "type": "module",
6
+ "main": "src/index.ts",
7
+ "files": [
8
+ "src/",
9
+ "agents/",
10
+ "core/",
11
+ "references/",
12
+ "SKILL.md",
13
+ "postinstall.mjs",
14
+ "preuninstall.mjs"
15
+ ],
16
+ "scripts": {
17
+ "postinstall": "node postinstall.mjs",
18
+ "preuninstall": "node preuninstall.mjs",
19
+ "init": "node init.mjs"
20
+ },
21
+ "keywords": [
22
+ "opencode",
23
+ "opencode-plugin",
24
+ "security",
25
+ "api-security",
26
+ "pentest",
27
+ "vulnerability-scanning"
28
+ ],
29
+ "author": "steveopen1",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/steveopen1/skill-play"
34
+ },
35
+ "homepage": "https://github.com/steveopen1/skill-play/tree/main/agent-plugins/OPENCODE/api-security-testing",
36
+ "peerDependencies": {
37
+ "@opencode-ai/plugin": "^1.1.19",
38
+ "@opencode-ai/sdk": "^1.1.19"
39
+ },
40
+ "dependencies": {
41
+ "@opencode-ai/plugin": "^1.1.19",
42
+ "@opencode-ai/sdk": "^1.1.19"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^25.5.2",
46
+ "typescript": "^6.0.2"
47
+ }
48
+ }
package/postinstall.mjs CHANGED
@@ -1,11 +1,10 @@
1
- #!/usr/bin/env node
2
-
3
1
  /**
4
2
  * postinstall.mjs - API Security Testing Plugin
5
3
  *
6
4
  * Installs:
7
- * 1. agents to ~/.config/opencode/agents/
8
- * 2. SKILL.md and references to ~/.config/opencode/skills/api-security-testing/
5
+ * 1. agents to ~/.claude/agents/ (oh-my-opencode discovery path)
6
+ * 2. agents to ~/.config/opencode/agents/ (OpenCode native discovery path)
7
+ * 3. SKILL.md and references to ~/.config/opencode/skills/api-security-testing/
9
8
  */
10
9
 
11
10
  import { copyFileSync, existsSync, mkdirSync, readdirSync } from "node:fs";
@@ -20,11 +19,42 @@ function getOpencodeBaseDir() {
20
19
  return join(home, ".config", "opencode");
21
20
  }
22
21
 
22
+ function getClaudeBaseDir() {
23
+ const home = process.env.HOME || process.env.USERPROFILE || "/root";
24
+ return join(home, ".claude");
25
+ }
26
+
27
+ function copyDirRecursive(src, dest) {
28
+ if (!existsSync(dest)) {
29
+ mkdirSync(dest, { recursive: true });
30
+ }
31
+ const items = readdirSync(src, { withFileTypes: true });
32
+ let count = 0;
33
+ for (const item of items) {
34
+ const srcPath = join(src, item.name);
35
+ const destPath = join(dest, item.name);
36
+ try {
37
+ if (item.isDirectory()) {
38
+ copyDirRecursive(srcPath, destPath);
39
+ } else {
40
+ copyFileSync(srcPath, destPath);
41
+ count++;
42
+ }
43
+ } catch (err) {
44
+ console.error(` ✗ ${item.name}: ${err.message}`);
45
+ }
46
+ }
47
+ return count;
48
+ }
49
+
23
50
  function main() {
24
51
  const packageRoot = __dirname;
25
52
  const agentsSourceDir = join(packageRoot, "agents");
26
- const agentsTargetDir = join(getOpencodeBaseDir(), "agents");
27
- const skillTargetDir = join(getOpencodeBaseDir(), "skills", "api-security-testing");
53
+ const opencodeBaseDir = getOpencodeBaseDir();
54
+ const claudeBaseDir = getClaudeBaseDir();
55
+ const opencodeAgentsDir = join(opencodeBaseDir, "agents");
56
+ const claudeAgentsDir = join(claudeBaseDir, "agents");
57
+ const skillTargetDir = join(opencodeBaseDir, "skills", "api-security-testing");
28
58
 
29
59
  console.log("[api-security-testing] Installing...");
30
60
  console.log(` Package root: ${packageRoot}`);
@@ -32,17 +62,17 @@ function main() {
32
62
  let totalInstalled = 0;
33
63
  let totalFailed = 0;
34
64
 
35
- // 1. Install agents
36
- console.log("\n[1/3] Installing agents...");
65
+ // 1. Install agents to BOTH locations (oh-my-opencode + OpenCode native)
66
+ console.log("\n[1/4] Installing agents to ~/.claude/agents/ (oh-my-opencode)...");
37
67
  if (existsSync(agentsSourceDir)) {
38
- if (!existsSync(agentsTargetDir)) {
39
- mkdirSync(agentsTargetDir, { recursive: true });
68
+ if (!existsSync(claudeAgentsDir)) {
69
+ mkdirSync(claudeAgentsDir, { recursive: true });
40
70
  }
41
71
 
42
72
  const files = readdirSync(agentsSourceDir).filter(f => f.endsWith(".md"));
43
73
  for (const file of files) {
44
74
  try {
45
- copyFileSync(join(agentsSourceDir, file), join(agentsTargetDir, file));
75
+ copyFileSync(join(agentsSourceDir, file), join(claudeAgentsDir, file));
46
76
  console.log(` ✓ ${file}`);
47
77
  totalInstalled++;
48
78
  } catch (err) {
@@ -52,8 +82,27 @@ function main() {
52
82
  }
53
83
  }
54
84
 
55
- // 2. Install SKILL.md
56
- console.log("\n[2/3] Installing SKILL.md...");
85
+ console.log("\n[2/4] Installing agents to ~/.config/opencode/agents/ (OpenCode native)...");
86
+ if (existsSync(agentsSourceDir)) {
87
+ if (!existsSync(opencodeAgentsDir)) {
88
+ mkdirSync(opencodeAgentsDir, { recursive: true });
89
+ }
90
+
91
+ const files = readdirSync(agentsSourceDir).filter(f => f.endsWith(".md"));
92
+ for (const file of files) {
93
+ try {
94
+ copyFileSync(join(agentsSourceDir, file), join(opencodeAgentsDir, file));
95
+ console.log(` ✓ ${file}`);
96
+ totalInstalled++;
97
+ } catch (err) {
98
+ console.error(` ✗ ${file}: ${err.message}`);
99
+ totalFailed++;
100
+ }
101
+ }
102
+ }
103
+
104
+ // 3. Install SKILL.md
105
+ console.log("\n[3/4] Installing SKILL.md...");
57
106
  const skillSource = join(packageRoot, "SKILL.md");
58
107
  if (existsSync(skillSource)) {
59
108
  if (!existsSync(skillTargetDir)) {
@@ -69,36 +118,15 @@ function main() {
69
118
  }
70
119
  }
71
120
 
72
- // 3. Install references
73
- console.log("\n[3/3] Installing references...");
121
+ // 4. Install references
122
+ console.log("\n[4/4] Installing references...");
74
123
  const refsSourceDir = join(packageRoot, "references");
75
124
  const refsTargetDir = join(skillTargetDir, "references");
76
125
  if (existsSync(refsSourceDir)) {
77
- if (!existsSync(refsTargetDir)) {
78
- mkdirSync(refsTargetDir, { recursive: true });
79
- }
80
-
81
- function copyDir(src, dest) {
82
- const items = readdirSync(src);
83
- for (const item of items) {
84
- const srcPath = join(src, item);
85
- const destPath = join(dest, item);
86
- try {
87
- copyFileSync(srcPath, destPath);
88
- totalInstalled++;
89
- } catch {
90
- if (existsSync(srcPath) && !srcPath.endsWith(".md")) {
91
- mkdirSync(destPath, { recursive: true });
92
- copyDir(srcPath, destPath);
93
- }
94
- }
95
- }
96
- }
97
-
98
126
  try {
99
- copyDir(refsSourceDir, refsTargetDir);
100
- console.log(" ✓ references/");
101
- totalInstalled++;
127
+ const count = copyDirRecursive(refsSourceDir, refsTargetDir);
128
+ totalInstalled += count;
129
+ console.log(` ✓ references/ (${count} files)`);
102
130
  } catch (err) {
103
131
  console.error(` ✗ references/: ${err.message}`);
104
132
  totalFailed++;
@@ -108,7 +136,8 @@ function main() {
108
136
  console.log(`\n========================================`);
109
137
  if (totalFailed === 0) {
110
138
  console.log(`✓ Installed ${totalInstalled} file(s)`);
111
- console.log(`\nAgents: ${agentsTargetDir}`);
139
+ console.log(`\nAgents (oh-my-opencode): ${claudeAgentsDir}`);
140
+ console.log(`Agents (OpenCode native): ${opencodeAgentsDir}`);
112
141
  console.log(`Skill: ${skillTargetDir}`);
113
142
  console.log(`\n⚠️ IMPORTANT: Restart OpenCode to discover new agents`);
114
143
  } else {
@@ -0,0 +1,72 @@
1
+ # API Security Testing 参考资源
2
+
3
+ ## 核心文件
4
+
5
+ | 文件 | 内容 |
6
+ |------|------|
7
+ | `pua-agent.md` | PUA自动测试Agent,强制深入不放弃 |
8
+ | `fuzzing-patterns.md` | API Fuzzing字典 |
9
+ | `report-template.md` | 安全测试报告模板 |
10
+
11
+ ## vulnerabilities/ 漏洞测试方法
12
+
13
+ | 文件 | 内容 |
14
+ |------|------|
15
+ | `vulnerabilities/01-sqli-tests.md` | SQL注入测试 + WAF绕过 |
16
+ | `vulnerabilities/02-user-enum-tests.md` | 用户枚举测试 |
17
+ | `vulnerabilities/03-jwt-tests.md` | JWT认证测试 |
18
+ | `vulnerabilities/04-idor-tests.md` | IDOR越权测试 |
19
+ | `vulnerabilities/05-sensitive-data-tests.md` | 敏感信息泄露 |
20
+ | `vulnerabilities/06-biz-logic-tests.md` | 业务逻辑漏洞 |
21
+ | `vulnerabilities/07-security-config-tests.md` | 安全配置漏洞 |
22
+ | `vulnerabilities/08-brute-force-tests.md` | 暴力破解测试 |
23
+ | `vulnerabilities/09-vulnerability-chains.md` | 漏洞关联联想 |
24
+ | `vulnerabilities/10-auth-tests.md` | OAuth/SAML/2FA测试 |
25
+ | `vulnerabilities/11-graphql-tests.md` | GraphQL安全测试 |
26
+ | `vulnerabilities/12-ssrf-tests.md` | SSRF测试 |
27
+
28
+ ## PUA Agent 使用
29
+
30
+ ### 核心思想
31
+
32
+ ```
33
+ 【PUA自动模式】
34
+ - 发现线索 → 自动深入
35
+ - 不等待用户指令
36
+ - 压力升级直到完成
37
+ ```
38
+
39
+ ### 压力升级机制
40
+
41
+ | 失败次数 | 级别 | 行动 |
42
+ |---------|------|------|
43
+ | 1次 | L1 | 换方法继续 |
44
+ | 2次 | L2 | 强制检查清单 |
45
+ | 3次 | L3 | 报告进度并继续 |
46
+ | 4次+ | L4 | 尝试其他方向 |
47
+
48
+ ### 不放弃原则
49
+
50
+ ```
51
+ 遇到以下情况必须继续:
52
+ □ 端点404 → 尝试POST方法
53
+ □ 被WAF拦截 → 换payload
54
+ □ 返回HTML → 继续API测试
55
+ □ 找不到配置 → 搜索其他JS
56
+ □ 一个端点失败 → 测试同类端点
57
+ □ 说"无法测试" → 必须穷举所有方法
58
+ ```
59
+
60
+ ### 进度追踪表
61
+
62
+ ```
63
+ 阶段1: [████████░░] 80%
64
+ 阶段2: [████░░░░░░░] 40%
65
+ 阶段3: [░░░░░░░░░░░] 0%
66
+ 阶段4: [░░░░░░░░░░░] 0%
67
+
68
+ 发现:
69
+ ├─ CORS漏洞: 18个端点
70
+ ├─ SQL注入: 待测试
71
+ └─ 新线索: /ipark-wxlite/*
72
+ ```
@@ -0,0 +1,119 @@
1
+ # Asset Discovery Guidance
2
+
3
+ 将原始 API 材料转换为紧凑的安全相关清单。
4
+
5
+ ## 目标
6
+
7
+ 识别对安全测试最重要的 API 部分。
8
+
9
+ ## 核心表面
10
+
11
+ - base URL(s)
12
+ - versioning scheme
13
+ - routes 或 operations
14
+ - methods
15
+ - content types
16
+ - auth schemes
17
+
18
+ ## 信任边界
19
+
20
+ - public vs authenticated endpoints
21
+ - user vs admin operations
22
+ - internal vs external APIs
23
+ - service-to-service 或 callback flows
24
+ - tenant 或 organization 边界
25
+
26
+ ## 敏感对象
27
+
28
+ 关注以下对象:
29
+ - users
30
+ - roles
31
+ - teams
32
+ - organizations
33
+ - invoices
34
+ - payments
35
+ - orders
36
+ - files
37
+ - secrets
38
+ - API keys
39
+ - tokens
40
+ - audit logs
41
+ - exports
42
+ - configuration objects
43
+
44
+ ## 高风险操作模式
45
+
46
+ 标记与以下相关的 endpoints 或 mutations:
47
+ - create/update/delete user
48
+ - role assignment
49
+ - permission change
50
+ - password reset
51
+ - token issue 或 refresh
52
+ - export 或 bulk download
53
+ - import 或 bulk update
54
+ - file upload
55
+ - webhook registration
56
+ - callback URL configuration
57
+ - search 或 filter on sensitive entities
58
+ - internal admin dashboards 或 debug endpoints
59
+
60
+ ## REST 提示
61
+
62
+ 优先包含模式的 endpoints:
63
+ - `/admin`
64
+ - `/internal`
65
+ - `/users`
66
+ - `/roles`
67
+ - `/permissions`
68
+ - `/export`
69
+ - `/import`
70
+ - `/search`
71
+ - `/upload`
72
+ - `/files`
73
+ - `/billing`
74
+ - `/settings`
75
+ - `/token`
76
+ - `/auth`
77
+ - `/debug`
78
+
79
+ 同时注意:
80
+ - bulk 操作
81
+ - object IDs in path 或 query
82
+ - 同一资源上隐藏的替代方法
83
+ - 不一致的版本化 endpoints
84
+
85
+ ## GraphQL 提示
86
+
87
+ 优先:
88
+ - 变更 roles、permissions 或 state 的 mutations
89
+ - 暴露嵌套对象遍历的 fields
90
+ - admin-only resolvers
91
+ - schema introspection 暴露
92
+ - 带敏感链接数据的宽对象图
93
+ - 可能意外扩展访问的 connection 或 pagination 模式
94
+
95
+ ## 资产摘要格式
96
+
97
+ 优先简洁输出:
98
+
99
+ ```
100
+ - Base URLs:
101
+ - API type:
102
+ - Auth schemes:
103
+ - Roles observed or assumed:
104
+ - Sensitive objects:
105
+ - High-risk operations:
106
+ - Trust boundaries:
107
+ - Unknown areas:
108
+ ```
109
+
110
+ ## 优先级规则
111
+
112
+ 当表面较大时,优先深度在:
113
+ 1. auth 和 role 变更
114
+ 2. user 和 tenant 数据
115
+ 3. export/import 和 bulk 操作
116
+ 4. file 和 callback 流程
117
+ 5. 金融或行政操作
118
+
119
+ 不要在低风险的只读 metadata endpoints 上浪费空间,除非它们支持更广泛的滥用路径。
@@ -0,0 +1,129 @@
1
+ # Fuzzing 字典
2
+
3
+ ## API前缀字典
4
+
5
+ ```python
6
+ common_api_prefixes = [
7
+ # 协议/网关
8
+ "/gateway", "/proxy", "/route", "/ingress",
9
+ "/api-gateway", "/openapi", "/open/api",
10
+ # 版本前缀
11
+ "/v1", "/v2", "/v3", "/v4", "/v5",
12
+ "/api/v1", "/api/v2", "/api/v3",
13
+ "/rest", "/rest/api", "/graphql",
14
+ # 管理后台
15
+ "/admin", "/admin/api", "/manager", "/backend",
16
+ "/backoffice", "/cms",
17
+ # 业务模块
18
+ "/user", "/users", "/member", "/members",
19
+ "/order", "/orders", "/trade", "/transaction",
20
+ "/product", "/goods", "/shop", "/store",
21
+ "/payment", "/pay", "/finance", "/account",
22
+ "/file", "/upload", "/oss", "/storage",
23
+ "/message", "/notify", "/sms", "/email",
24
+ "/admin", "/authority", "/system", "/config",
25
+ # 微服务
26
+ "/service", "/services", "/rpc", "/grpc",
27
+ "/auth", "/oauth", "/sso", "/cas",
28
+ # 移动端
29
+ "/mobile", "/app", "/ios", "/android",
30
+ "/miniapp", "/wechat", "/applet",
31
+ ]
32
+ ```
33
+
34
+ ## API端点字典
35
+
36
+ ```python
37
+ common_api_endpoints = [
38
+ # 通用CRUD
39
+ "login", "logout", "register", "list", "add", "delete", "modify",
40
+ "getList", "getListOfPage", "detail", "getInfo", "profile",
41
+ # 用户相关
42
+ "user", "user/list", "user/add", "user/delete", "user/modify",
43
+ "user/profile", "user/restPassword", "user/enable", "user/disable",
44
+ # 角色权限
45
+ "role", "role/list", "role/add", "role/delete", "role/modify",
46
+ "menu", "menu/list", "menu/add", "menu/delete", "menu/modify",
47
+ # 文件操作
48
+ "file", "upload", "download", "import", "export",
49
+ "imgUpload", "avatar", "attachment",
50
+ ]
51
+ ```
52
+
53
+ ## Fuzzing测试流程
54
+
55
+ ```python
56
+ for prefix in common_api_prefixes:
57
+ for endpoint in common_api_endpoints:
58
+ url = target + prefix + "/" + endpoint
59
+ response = requests.get(url)
60
+ # 记录返回200的接口
61
+ ```
62
+
63
+ ## API根路径探测
64
+
65
+ ```python
66
+ root_paths = [
67
+ "/", "/login", "/auth", "/oauth", "/sso", "/cas",
68
+ "/health", "/healthz", "/ready", "/status", "/info",
69
+ "/metrics", "/ping", "/actuator",
70
+ ]
71
+
72
+ for path in root_paths:
73
+ url = api_base + path
74
+ response = requests.get(url)
75
+ if "json" in response.headers.get("Content-Type", ""):
76
+ # 发现可访问的接口
77
+ ```
78
+
79
+ ## 业务端点模板扩展
80
+
81
+ ```
82
+ 发现的模式: /{module}/{operation}
83
+ 可能存在的端点:
84
+ - /{module}/list → 列表查询
85
+ - /{module}/add → 新增创建
86
+ - /{module}/modify → 修改更新
87
+ - /{module}/delete → 删除操作
88
+ - /{module}/detail → 详情查看
89
+ - /{module}/getInfo → 信息获取
90
+ - /{module}/export → 导出数据
91
+ - /{module}/import → 导入数据
92
+
93
+ RESTful风格:
94
+ - GET /{resource}/{id} → 获取详情
95
+ - PUT /{resource}/{id} → 完整更新
96
+ - DELETE /{resource}/{id} → 删除资源
97
+ - PATCH /{resource}/{id} → 部分更新
98
+ ```
99
+
100
+ ## 非通用base_path字典
101
+
102
+ ```python
103
+ extended_base_paths = [
104
+ # 协议/网关
105
+ "/gateway", "/proxy", "/route", "/ingress",
106
+ "/api-gateway", "/openapi", "/open/api",
107
+ # 版本前缀
108
+ "/v1", "/v2", "/v3", "/v4", "/v5",
109
+ "/api/v1", "/api/v2", "/api/v3",
110
+ "/rest", "/rest/api", "/graphql",
111
+ # 管理后台
112
+ "/admin", "/manager", "/manage", "/console",
113
+ "/backend", "/backoffice", "/cms",
114
+ # 业务模块
115
+ "/user", "/users", "/member", "/members",
116
+ "/order", "/orders", "/trade", "/transaction",
117
+ "/product", "/goods", "/shop", "/store",
118
+ "/payment", "/pay", "/finance", "/account",
119
+ "/file", "/upload", "/oss", "/storage",
120
+ "/message", "/notify", "/sms", "/email",
121
+ "/admin", "/authority", "/system", "/config",
122
+ # 微服务
123
+ "/service", "/services", "/rpc", "/grpc",
124
+ "/auth", "/oauth", "/sso", "/cas",
125
+ # 移动端
126
+ "/mobile", "/app", "/ios", "/android",
127
+ "/miniapp", "/wechat", "/applet",
128
+ ]
129
+ ```
@@ -0,0 +1,108 @@
1
+ # GraphQL Guidance
2
+
3
+ 分析 GraphQL API 时使用。
4
+
5
+ ## 关注领域
6
+
7
+ ### 字段级授权
8
+
9
+ - resolver 是否正确检查权限
10
+ - 嵌套查询是否泄露数据
11
+ - 是否缺少 admin-only 字段
12
+
13
+ ### 嵌套遍历
14
+
15
+ - `type User { friends: [User!]! }` 可导致递归查询
16
+ - `type Post { author: User }` 允许遍历
17
+ - 是否限制遍历深度
18
+
19
+ ### Resolver 边界
20
+
21
+ - 一个 resolver 是否调用另一个 service
22
+ - 是否存在 SSRF 风险
23
+ - 是否有命令注入点
24
+
25
+ ### Mutation 滥用
26
+
27
+ - 未经授权的状态变更
28
+ - 条件 mutation(如 admin-only mutation)
29
+ - 批量 mutation 导致的问题
30
+
31
+ ### Introspection 暴露
32
+
33
+ - 是否禁用 introspection
34
+ - 是否暴露敏感字段
35
+ - Schema 文档是否包含敏感信息
36
+
37
+ ## 常见风险信号
38
+
39
+ - ` IntrospectionQuery` 可访问
40
+ - 缺少 query 复杂度限制
41
+ - 缺少 query 深度限制
42
+ - 缺少字段权限检查
43
+ - mutation 接受任意输入
44
+ - 嵌套查询无限制
45
+
46
+ ## 测试重点
47
+
48
+ ### 1. 枚举攻击
49
+
50
+ ```graphql
51
+ # 枚举所有用户
52
+ query {
53
+ users {
54
+ id
55
+ username
56
+ email
57
+ }
58
+ }
59
+ ```
60
+
61
+ ### 2. 嵌套遍历
62
+
63
+ ```graphql
64
+ # 递归遍历 friendships
65
+ query {
66
+ user(id: 1) {
67
+ friends {
68
+ friends {
69
+ friends {
70
+ id
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ ### 3. 权限绕过
79
+
80
+ ```graphql
81
+ # 尝试 admin 字段
82
+ query {
83
+ user(id: 1) {
84
+ isAdmin
85
+ role
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### 4. mutation 滥用
91
+
92
+ ```graphql
93
+ # 未经授权的 mutation
94
+ mutation {
95
+ updateUser(id: 1, role: "admin") {
96
+ id
97
+ role
98
+ }
99
+ }
100
+ ```
101
+
102
+ ## 防护检查
103
+
104
+ - [ ] 是否限制查询复杂度
105
+ - [ ] 是否限制查询深度
106
+ - [ ] 是否禁用 introspection
107
+ - [ ] resolver 是否有权限检查
108
+ - [ ] 是否过滤敏感字段