| Title | Jeecg JeecgBoot <3.9.2 broken access controll |
|---|
| Description | ## Vulnerability Analysis
Some sensitive endpoints in `AiragModelController` are missing `@RequiresPermissions` authorization annotations. A normal authenticated user can access the model configuration export endpoint `/airag/airagModel/exportXls` and may export the `credential` field in the `AiragModel` entity. This field is used to store credentials for AI providers, such as API keys for `OpenAI`, `DeepSeek`, and others.
In addition, the `/airag/airagModel/test` endpoint is also missing permission protection. An attacker can craft a model configuration request body to trigger server-side calls to LLM, embedding, or image model APIs, causing unauthorized usage of model capabilities and quota consumption. It can also be used to verify whether a leaked API key is valid.
File: **AiragModelController.java**
```java
@Tag(name = "AiRag model configuration")
@RestController
@RequestMapping("/airag/airagModel")
@Slf4j
public class AiragModelController extends JeecgController<AiragModel, IAiragModelService> {
@Autowired
private IAiragModelService airagModelService;
@Autowired
AIChatHandler aiChatHandler;
```
The controller base path is:
```
/airag/airagModel
```
**Key Source 1: Protected add/edit endpoints for comparison**
In the same controller, the add and edit endpoints do have permission annotations:
```java
@PostMapping(value = "/add")
@RequiresPermissions("airag:model:add")
public Result<String> add(@RequestBody AiragModel airagModel) {
AssertUtils.assertNotEmpty("模型名称不能为空", airagModel.getName());
AssertUtils.assertNotEmpty("模型类型不能为空", airagModel.getModelType());
AssertUtils.assertNotEmpty("基础模型不能为空", airagModel.getModelName());
if(oConvertUtils.isObjectEmpty(airagModel.getActivateFlag())){
airagModel.setActivateFlag(0);
}
airagModelService.save(airagModel);
return Result.OK("添加成功!");
}
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
@RequiresPermissions("airag:model:edit")
public Result<String> edit(@RequestBody AiragModel airagModel) {
airagModelService.updateById(airagModel);
return Result.OK("编辑成功!");
}
```
This shows that the developer already treats model configuration as an administrative function that should be access-controlled. However, the later `list`, `queryById`, `exportXls`, and `test` endpoints are missing the same level of permission protection, creating an access control gap.
**Key Source 2: Unauthorized export of model configuration**
```java
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, AiragModel airagModel) {
return super.exportXls(request, airagModel, AiragModel.class, "AiRag模型配置");
}
```
## Reproduction
After obtaining a low-privilege user token, you can directly use the included `poc.py` to export the API key.
You can also test it with Burp:
<img width="1875" height="1489" alt="Image" src="https://github.com/user-attachments/assets/2a0322b2-749c-4bb7-a13f-d3ff9a2111f1" />
The exported table looks like this:
<img width="1902" height="700" alt="Image" src="https://github.com/user-attachments/assets/466c5b7c-f629-4f37-b2df-6114d1eab6d0" />
The API key can be obtained.
## Recommended Fixes
1. Add permission annotations to sensitive endpoints:
```java
@RequiresPermissions("airag:model:list")
@GetMapping(value = "/list")
@RequiresPermissions("airag:model:queryById")
@GetMapping(value = "/queryById")
@RequiresPermissions("airag:model:exportXls")
@RequestMapping(value = "/exportXls")
@RequiresPermissions("airag:model:test")
@PostMapping(value = "/test")
```
1. Prevent the `credential` field from appearing in normal responses and export files:
```java
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String credential;
```
or:
```java
@JsonIgnore private String credential;
```
1. Use a dedicated VO for Excel export instead of exporting the entity class `AiragModel.class` directly. |
|---|
| Source | ⚠️ https://github.com/jeecgboot/JeecgBoot/issues/9600 |
|---|
| User | lincoke (UID 100021) |
|---|
| Submission | 07/21/2026 07:53 (2 months ago) |
|---|
| Moderation | 09/06/2026 06:13 (2 months later) |
|---|
| Status | Accepted |
|---|
| VulDB entry | 399381 [JeecgBoot up to 3.9.3 AiragModelController.java exportXls credential access control] |
|---|
| Points | 20 |
|---|