skills/java-route-mapper/SKILL.md
Java Web 源码路由与参数映射分析工具。从源码中提取**所有** HTTP 路由和参数结构,并自动保存为 MD 文档。适用于:(1) 无 API 文档的项目完整接口梳理,(2) 下游漏洞审计 Skill 的路由数据源,(3) 源码端点完整分析。支持 Spring MVC、Servlet、JAX-RS、Struts 2、CXF Web Services 等框架。**必须输出所有接口,不省略任何内容,包括 Web Service 的完整 SOAP 方法**。
npx skillsauth add ruoji6/java-audit-skills java-route-mapperInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
从 Java Web 项目源码中提取所有 HTTP 路由与请求参数结构,为下游漏洞审计 Skill 提供完整的路由数据。不进行安全漏洞评估、代码质量分析或任何路由提取范围之外的内容输出。
此技能必须输出所有发现的接口,不允许省略。
以下规则为强制性要求,违反任何一条都会导致输出不合格。
核心策略:通配符路由必须全部识别,但不重复完整模板。每个 namespace 的通配符配置只写一次模式族头部(含 HTTP 方法、Content-Type、参数结构来源),下方只列出 URL → 入口方法签名 的映射列表。下游 agent 需要参数结构时通过反编译自取。
不允许:每个展开后的 URL 都重复完整模板(HTTP方法、Content-Type、参数结构等)—— 这会造成数十倍的 token 浪费且无信息增益。
适用场景(struts.xml 中存在):
name="*_*" 双通配 / name="user_*" 单通配 / name="*" 全匹配强制执行步骤:
<action name="*_*" class="{1}Action" method="{2}">
=== Pattern: {action}_{method}.action (namespace: /admin) ===
入口模板: {ActionClass}.{methodName}()
HTTP 方法: POST
Content-Type: application/x-www-form-urlencoded
参数来源: 各 Action 类的字段(下游 agent-5 反编译时提取)
展开实例(共 {N} 个):
- /admin/user_login.action → UserAction.login()
- /admin/user_logout.action → UserAction.logout()
- /admin/user_register.action → UserAction.register()
- ... [逐行列出全部 N 个,禁止省略,禁止用 "..." / "等" / "其余"]
路径变量({id}、/**)不属于通配符展开——同一 controller 方法处理全部路径变量值,无需展开实例。直接按普通路由格式输出,参数结构中标注 Path: {id}:Long。
同 1.2,路径参数(@PathParam)按普通路由格式输出,不展开实例。
适用场景:/api/*、*.do 等。若 Servlet 使用 request.getPathInfo() 内部分发到不同方法,必须按模式族 + 实例列表输出(参考 1.1 格式);否则按普通路由处理。
Web Service 的 URL 路径必须从配置文件中读取,绝对不能根据类名或 endpoint id 推断!
解析优先级(按顺序执行):
URL 组成公式:
完整URL = 上下文路径 + web.xml中的Servlet映射 + address属性值
示例: /myapp + /services/ + /UserApi = /myapp/services/UserApi
错误示例(必须避免):
UserServiceImpl → /UserServiceuserWebService → /userWebServiceaddress="/UserApi" → /myapp/services/UserApi强制执行步骤:
从配置文件获取所有 endpoint
<jaxws:endpoint id="userService"
implementor="#userServiceImpl"
address="/UserService"/>
反编译每个 Service 实现类
提取所有 public 方法 - 方法名、参数列表、返回类型
为每个方法记录完整的方法签名和参数列表
记录配置来源 - 配置文件路径、行号、address 属性值、implementor 类名
强制执行步骤:
读取 server-config.wsdd 或 services.xml
<service name="UserService" provider="java:RPC">
<parameter name="className" value="com.example.UserService"/>
</service>
提取服务名和实现类
反编译实现类获取方法列表
URL 组成: /axis/services/{serviceName}
对于使用 interfaceId 参数路由的通用执行接口:
以下输出格式绝对禁止使用:
| 禁止模式 | 错误示例 | 正确做法 |
|:---------|:---------|:---------|
| 使用"等"省略 | LoginAction, UserAction等 | 列出全部 Action |
| 使用"..."省略 | method1, method2, ... | 列出全部方法 |
| 使用"其他"省略 | 以及其他20个方法 | 列出全部20个方法 |
| 使用"更多"省略 | 更多接口请查看源码 | 直接列出所有接口 |
| 使用占位符 | {action}_{method}.action | 展开为实际 URL |
| 使用范围表示 | 001 ~ 050 | 逐个列出 001, 002, ..., 050 |
| 描述替代列表 | 方法列表: 用户管理相关 | 列出具体方法名 |
| 只给 WSDL 地址 | 请通过 WSDL 查看可用方法 | 列出所有 SOAP 方法 |
| 只列类名不列方法 | UserAction 支持多个方法 | 列出每个方法的完整模板 |
=== [1] login_login.action ===
URL: `/admin/login_login.action`
方法: LoginAction.login()
HTTP 方法: POST
Content-Type: application/x-www-form-urlencoded
参数结构:
Body: loginName (String), password (String)
=== [1] GET /api/users/{id} ===
位置: UserController.getUser (UserController.java:45)
HTTP 方法: GET
URL 路径: /api/users/{id}
参数结构:
Path: {id} (Long) - 用户ID
Header: Authorization - Bearer Token
=== [1] GET /rest/users/{userId} ===
位置: UserResource.getUser (UserResource.java:32)
HTTP 方法: GET
URL 路径: /rest/users/{userId}
参数结构:
Path: {userId} (Long)
Query: includeOrders (boolean, 可选)
=== [1] POST /api/upload ===
位置: UploadServlet.doPost (UploadServlet.java:28)
HTTP 方法: POST
URL 路径: /api/upload
参数结构:
Body: multipart/form-data
- file (File) - 上传文件
- description (String) - 文件描述
### UserService (共 5 个方法)
- **配置文件**: applicationContext.xml:42
- **address 属性**: /UserApi
- **完整 URL**: /myapp/services/UserApi
=== [WS-1] login ===
方法签名: login(String loginName, String password)
返回类型: String
参数结构:
Body: SOAP XML
- loginName (String) - 登录名
- password (String) - 密码
此验证必须通过才能写入文件,验证不通过时必须返回补充内容。
| 检查项 | 计算公式 | 通过条件 | |:-------|:---------|:---------| | Struts2 路由 | 实际接口数 ÷ Action类数 | ≥ 3 | | Spring MVC 接口 | 实际接口数 ÷ Controller类数 | ≥ 2 | | JAX-RS 接口 | 实际接口数 ÷ Resource类数 | ≥ 2 | | Servlet 接口 | 实际接口数 ÷ Servlet类数 | ≥ 1 | | Web Service 方法 | 实际接口数 ÷ 反编译获得的方法数 | = 100% |
扫描输出内容,检测到任何省略标志时必须替换为完整内容。
在标记任务完成前,必须执行以下检查:
□ 主索引中列出的每个模块都已生成对应的详情文件
演示案例:
==========
假设主索引文件的"模块索引"表格如下:
| 模块 | 文件 | 接口数量 |
|:-----|:-------|:-----|
| admin | [admin/myapp_module_admin.md](admin/myapp_module_admin.md) | 218 |
| user | [user/myapp_module_user.md](user/myapp_module_user.md) | 85 |
| api | [api/myapp_module_api.md](api/myapp_module_api.md) | 45 |
验证步骤:
1. 检查 admin/myapp_module_admin.md 是否存在
2. 检查 user/myapp_module_user.md 是否存在
3. 检查 api/myapp_module_api.md 是否存在
4. 确认模块数量(3) = 实际文件数量(3)
□ Web Service 索引中的每个服务都已生成对应的详情文件
□ 没有"详见xxx"但xxx文件不存在的情况
□ 文件数量一致性
演示案例:主索引列出5个模块 → 必须有5个对应的模块子目录,且每个子目录中都有对应的 module_xxx.md 文件
□ 文件名一致性
演示案例:主索引引用 admin/myapp_module_admin.md → 实际相对路径和文件名必须完全匹配
□ 链接有效性
演示案例:点击主索引中的 [admin/myapp_module_admin.md] 链接应能成功打开
□ 每个详情文件都包含:
- 模块概览(项目名称、上下文路径、框架)
- 框架配置(配置文件位置)
- 路由详细列表(每个接口的完整信息)
□ 对于空模块(无路由的模块):
演示案例:
==========
某模块 upload 只有静态资源,没有业务路由
正确做法:仍然生成 upload/myapp_module_upload.md
```markdown
# MyApp - upload 模块详情
## 模块概览
该模块主要用于静态文件上传,未检测到业务路由。
## 检查结果
- WEB-INF目录:不存在
- 配置文件:无
- 路由接口:无
错误做法:跳过不生成文件
#### 6.4 执行验证命令
**演示案例:在完成所有文件生成后,运行以下命令验证**
```bash
# 假设项目名称为 myapp,输出目录为 route_mapper/,生成的文件如下:
# route_mapper/myapp_route_mapper_20260129.md (主索引)
# route_mapper/admin/myapp_module_admin_20260129.md (admin模块)
# route_mapper/user/myapp_module_user_20260129.md (user模块)
# route_mapper/api/myapp_module_api_20260129.md (api模块)
# 验证命令1: 检查生成的模块子目录和文件
find route_mapper/ -name "*_module_*.md" -type f
# 预期输出:应该看到3个模块详情文件
# 验证命令2: 从主索引中提取所有引用的文件路径
grep -oP '[a-z]+/myapp_module_[^)]*md' route_mapper/myapp_route_mapper_20260129.md | sort -u
# 验证命令3: 检查引用的文件是否都存在
grep -oP '[a-z]+/myapp_[^)]*md' route_mapper/myapp_route_mapper_20260129.md | while read f; do
if [ ! -f "route_mapper/$f" ]; then
echo "❌ 缺失文件: route_mapper/$f"
else
echo "✅ 存在文件: route_mapper/$f"
fi
done
演示案例:完整的检查流程
假设分析了一个名为 myshop 的电商项目,包含以下模块:
步骤1: 生成主索引文件
✅ route_mapper/myshop_route_mapper_20260129.md
步骤2: 检查主索引中的模块列表
主索引显示:product, order, user, payment (4个模块)
步骤3: 验证模块子目录和详情文件是否存在
✅ route_mapper/product/myshop_module_product_20260129.md
✅ route_mapper/order/myshop_module_order_20260129.md
✅ route_mapper/user/myshop_module_user_20260129.md
✅ route_mapper/payment/myshop_module_payment_20260129.md
步骤4: 生成README文档(**仅 standalone 模式**;pipeline/多 agent 模式下由 agent-1-merge 统一生成,worker 跳过此步骤)
✅ route_mapper/myshop_README_20260129.md
步骤5: 执行验证命令
$ find route_mapper/ -name "*_module_*.md" -type f | wc -l
4 (与主索引中模块数量一致)
步骤6: 确认完成
所有检查项通过 → 可以标记任务完成
只有在以下条件全部满足时,才能标记任务为完成:
如果发现缺失文件,必须:
输入: 项目源码路径
可选: 项目上下文路径、已知框架信息
初始化步骤:
多框架支持: 一个项目可能同时使用多种 Web 框架,需要分别识别并制定分析任务。
| 框架 | 识别特征 | 参考资料 |
|------|---------|---------|
| Spring MVC | @Controller、@RequestMapping | SPRING_MVC.md |
| Spring Boot | application.properties/yml、Spring Boot starter | SPRING_MVC.md |
| Servlet | web.xml、@WebServlet | SERVLET.md |
| JAX-RS | @Path、@GET、@POST | JAXRS.md |
| Struts 2 | struts.xml | STRUTS.md |
| CXF Web Services | /ws/*、@WebService、applicationContext.xml | WEBSERVICE.md |
任务制定规则:
扫描项目源码,提取所有对外可访问的 HTTP 路由。
扫描范围:
@Controller / @RestController 类@RequestMapping 及其变体注解输出信息:
对每个路由解析其参数结构。
参数来源:
@PathVariable、@PathParam@RequestParam、@QueryParam@RequestBody、请求对象、Form 表单@RequestHeader、@HeaderParam@CookieValue、@CookieParam参数类型解析:
当接口定义或方法签名位于已编译的 .class 文件或第三方 JAR 中时:
反编译策略:
重要:必须输出所有发现的接口,不要省略或使用摘要。
为每个接口生成完整的路由与参数结构记录,包含:
禁止的操作:
强制要求:
要求的输出格式(每条):
=== [序号] 接口标识 ===
注解: (仅复制源码中的 @ApiOperation 或 Javadoc 原文,无注解时留空)
位置: ClassName.methodName (源文件:行号)
HTTP 方法: GET/POST/PUT/DELETE 等
URL 路径: /完整/路径/结构
Content-Type: application/json 等
参数结构:
Path: {pathVar1}, {pathVar2}
Query: param1, param2 (类型: String)
Body: ContentType (类型定义)
Header: X-Custom-Header
Cookie: sessionId
输出必须为 MD 文件格式,按层级目录拆分(一个层级一个 MD 文件)。
当接口数量较大时,必须拆分输出文件以确保每个接口都有完整的模板。
满足以下任一条件时触发拆分:
按模块建子目录,文件名动态生成。
| 文件类型 | 命名格式 | 示例 |
|---------|---------|------|
| 主索引 | route_mapper/{项目名}_route_mapper_{时间戳}.md | route_mapper/myapp_route_mapper_20260121.md |
| 模块详情 | route_mapper/{模块名}/{项目名}_module_{模块名}_{时间戳}.md | route_mapper/admin/myapp_module_admin_20260121.md |
| Web Service | route_mapper/webservice/{项目名}_ws_{服务名}_{时间戳}.md | route_mapper/webservice/myapp_ws_userservice_20260121.md |
| Namespace 拆分 | route_mapper/{模块名}/{项目名}_{namespace}_{时间戳}.md | route_mapper/admin/myapp_admin_user_20260121.md |
| README | route_mapper/{项目名}_README_{时间戳}.md | route_mapper/myapp_README_20260121.md |
目录创建规则:
route_mapper/ 根目录route_mapper/{模块名}/ 子目录下route_mapper/webservice/ 子目录下mkdir -p)动态模块名示例:
| 实际模块/namespace | 子目录 | 生成的文件名 |
|------------------|:------|:-------------|
| admin | admin/ | admin/myapp_module_admin_20260121.md |
| user | user/ | user/myapp_module_user_20260121.md |
| config | config/ | config/myapp_module_config_20260121.md |
| api | api/ | api/myapp_module_api_20260121.md |
| product | product/ | product/myapp_module_product_20260121.md |
| order | order/ | order/myapp_module_order_20260121.md |
| / (root namespace) | root/ | root/myapp_module_root_20260121.md |
模块识别来源:
/services/, /ws/策略 A: 按模块子目录拆分(推荐)
每个模块一个子目录,主索引放根目录:
route_mapper/
├── {project_name}_route_mapper_{timestamp}.md # 主索引文件(根目录)
├── {project_name}_README_{timestamp}.md # 说明文档(根目录)
├── admin/ # admin 模块子目录
│ └── {project_name}_module_admin_{timestamp}.md # 接口 ≤ 50 → 单文件
├── user/ # user 模块子目录
│ ├── {project_name}_module_user_{timestamp}.md # 接口 > 50 → 模块概览 + namespace 拆分
│ ├── {project_name}_user_manage_{timestamp}.md # namespace 详情
│ └── {project_name}_user_auth_{timestamp}.md # namespace 详情
└── webservice/ # Web Service 子目录
└── {project_name}_ws_orderService_{timestamp}.md
主索引文件中的链接指向子目录:
## 模块索引
| 模块 | 文件 | 接口数量 | 框架 |
|:-----|:-------|:-----|:-----|
| admin | [admin/myapp_module_admin_20260121.md](admin/myapp_module_admin_20260121.md) | 35 | Struts2 |
| user | [user/myapp_module_user_20260121.md](user/myapp_module_user_20260121.md) | 218 | Struts2+Spring |
## Web Service 索引
| 服务 | 文件 | 方法数量 |
|:-----|:----|:--------|
| OrderService | [webservice/myapp_ws_orderService_20260121.md](webservice/myapp_ws_orderService_20260121.md) | 40 |
拆分触发规则:
| 条件 | 行为 | |:-----|:-----| | 模块接口 ≤ 50 | 单文件放在模块子目录下 | | 模块接口 > 50 | 模块概览 + 按 namespace 拆分,都放在模块子目录下 |
策略 B: 按 namespace 拆分(适用于单模块接口极多的情况)
当单模块接口 > 50 时,在该模块子目录内按 namespace 继续拆分:
route_mapper/admin/
├── {project_name}_module_admin_{timestamp}.md # 模块概览(含子文件索引)
├── {project_name}_admin_device_{timestamp}.md # /device namespace
├── {project_name}_admin_channel_{timestamp}.md # /channel namespace
└── {project_name}_admin_login_{timestamp}.md # / namespace (登录相关)
先分析,再拆分
生成主索引文件
创建模块子目录并生成详情文件
mkdir -p {output_path}/route_mapper/{模块名}/mkdir -p {output_path}/route_mapper/webservice/保证可追溯性
admin/myapp_module_admin_xxx.md)对于 execute 类型或类似动态调用的 Web Service:
错误做法:
#### UserService
支持的方法ID: user_001_001, user_001_002, ... (共40个)
正确做法 - 拆分为独立文件:
主文件:
#### UserService (服务路径: /services/UserService)
详细方法列表见: [webservice/myapp_ws_user_20260121.md](webservice/myapp_ws_user_20260121.md)
详情文件 webservice/myapp_ws_user_20260121.md:
# UserService 方法详情
=== [1] user.create ===
方法ID: user_001_001
描述: 创建用户
参数: {"username": "...", "email": "...", "role": "..."}
方法签名: executeInterface(String interfaceId, String jsonParam)
Content-Type: text/xml; charset=utf-8
完整 URL: /admin/services/UserService
参数结构:
Body: SOAP XML
- interfaceId: user_001_001
- jsonParam: {"username": "...", "email": "...", "role": "..."}
=== [2] user.update ===
[完整参数结构]
[所有40个方法都有完整参数结构...]
严格按照 references/ 目录中的填充式模板生成输出文件。
| 文件类型 | 模板 | 命名格式 | 数量 |
|---------|------|---------|------|
| 主索引 | OUTPUT_TEMPLATE_INDEX.md | route_mapper/{project_name}_route_mapper_{YYYYMMDD_HHMMSS}.md | 1 个 |
| 模块详情 | OUTPUT_TEMPLATE_MODULE.md | route_mapper/{module_name}/{project_name}_module_{module_name}_{YYYYMMDD_HHMMSS}.md | N 个(按模块) |
| WS 详情 | OUTPUT_TEMPLATE_MODULE.md | route_mapper/webservice/{project_name}_ws_{service_name}_{YYYYMMDD_HHMMSS}.md | N 个(按服务) |
| 说明文档 | OUTPUT_TEMPLATE_README.md | route_mapper/{project_name}_route_README_{YYYYMMDD_HHMMSS}.md | 1 个(pipeline 模式下由 agent-1-merge 写;worker 不生成) |
关键规则:
保存步骤:
当满足以下任一条件时,启用分批处理:
步骤 1:按 namespace/模块分组 步骤 2:逐个 namespace 处理(反编译 → 提取方法 → 生成参数结构 → 验证 → 写入) 步骤 3:增量写入(每完成 10 个接口立即写入文件) 步骤 4:进度检查点(每个 namespace 完成后验证接口数量)
对于大型项目,按模块子目录 + namespace 拆分文件:
route_mapper/
├── {project}_route_mapper_{date}.md # 主索引
├── {module}/
│ ├── {project}_module_{module}_{date}.md # 模块概览
│ └── {project}_{module}_{namespace}_{date}.md # namespace 详情
└── webservice/
└── {project}_ws_{service}_{date}.md # Web Service 详情
当检测到省略内容时,自动执行修正:
| 检测到的问题 | 自动修正动作 |
|:-------------|:-------------|
| Action1, Action2等 | 反编译获取完整 Action 列表,替换为全部 |
| {action}_{method}.action | 反编译获取实际方法,展开为具体 URL |
| 方法列表: 描述文字 | 反编译获取方法签名,替换为具体方法 |
| 共N个方法 但列出 < N | 补充缺失的方法直到数量匹配 |
| interfaceId: xxx ~ yyy | 展开为逐个 interfaceId |
| 问题 | 解决方案 |
|:-----|:---------|
| 无法识别框架 | 检查项目根目录的配置文件,参考 FRAMEWORK_PATTERNS.md |
| 路由路径不完整 | 检查类级别的 @RequestMapping 和上下文路径配置 |
| 参数类型未知 | 使用反编译工具获取完整的类型定义 |
| 生成的路由信息不完整 | 确认未受安全拦截器/过滤器限制 |
| 模块名不是预期的 | 文件名是动态生成的,根据实际发现的模块/namespace 生成 |
development
Java Web 源码 XXE (XML External Entity) 漏洞审计工具。从源码中识别所有 XML 解析操作并检测外部实体注入漏洞。适用于:(1) 识别 XML 解析器类型和实现方式,(2) 发现 XXE 注入漏洞,(3) 检查外部实体防护配置情况,(4) 审计 XML 输入来源与回显逻辑。支持 XMLReader、SAXBuilder、SAXReader、SAXParserFactory、DocumentBuilderFactory 五种主流解析器。**支持反编译 .class/.jar 文件提取 XML 解析逻辑**。结合 java-route-mapper 使用可实现完整的路由+XXE审计。
development
Java 组件版本漏洞检测工具。扫描 pom.xml、build.gradle 或 jar 文件中的第三方依赖,匹配已知漏洞规则(CVE)并生成漏洞检测报告。适用于:(1) Java 项目依赖安全审计,(2) 识别 Log4j、Fastjson、Shiro、Spring 等高危组件漏洞,(3) jar 包反编译后的依赖提取。支持按目录层级分组输出,支持通过 CFR 反编译 .class/.jar 文件提取依赖信息。
development
Java Web 源码 SQL 注入漏洞审计工具。从源码中定位所有 SQL 执行入口并检测注入漏洞。适用于:(1) 识别 SQL 执行框架和实现方式,(2) 发现 SQL 注入漏洞,(3) 检查参数化查询使用情况,(4) 检测动态 SQL 拼接漏洞。支持 JDBC、MyBatis、Hibernate 三种主流框架。**支持反编译 .class/.jar 文件提取 SQL 逻辑**。结合 java-route-mapper 使用可实现完整的路由+SQL注入审计。
development
Java Web 源码路由多层级调用链追踪工具。根据用户指定的路由路径,追踪从 Controller/Action 到 DAO 层的完整调用链,输出每一层的文件位置、方法签名和可传入参数。适用于多种漏洞类型的参数流向追踪:(1) SQL注入 - 追踪参数到SQL拼接点,(2) 命令注入 - 追踪参数到Runtime.exec(),(3) SSRF - 追踪参数到HTTP请求,(4) XSS - 追踪参数到响应输出,(5) 文件操作 - 追踪参数到File操作,(6) XXE/反序列化/LDAP注入/表达式注入等。支持 Spring MVC、Struts 2、Servlet、JAX-RS 等框架。**支持反编译 .class/.jar 文件提取调用链**。结合 java-route-mapper 使用可实现完整的路由+调用链审计。