elunez/eladmin · error · BadRequestException
文件只能上传在opt目录或者home目录
Error message
文件只能上传在opt目录或者home目录
What it means
AppServiceImpl.verification (called from create/update) enforces that App.uploadPath starts with '/opt' or '/home'; otherwise BadRequestException('文件只能上传在opt目录或者home目录 '). The whitelist restricts where uploaded deploy packages may be written on the server, limiting path-traversal/arbitrary-write risk.
Source
Thrown at eladmin-system/src/main/java/me/zhengjie/modules/maint/service/impl/AppServiceImpl.java:95
@Transactional(rollbackFor = Exception.class)
public void update(App resources) {
// 验证应用名称是否存在恶意攻击payload,https://github.com/elunez/eladmin/issues/873
String appName = resources.getName();
if (appName.contains(";") || appName.contains("|") || appName.contains("&")) {
throw new IllegalArgumentException("非法的应用名称,请勿包含[; | &]等特殊字符");
}
verification(resources);
App app = appRepository.findById(resources.getId()).orElseGet(App::new);
ValidationUtil.isNull(app.getId(),"App","id",resources.getId());
app.copy(resources);
appRepository.save(app);
}
private void verification(App resources){
String opt = "/opt";
String home = "/home";
if (!(resources.getUploadPath().startsWith(opt) || resources.getUploadPath().startsWith(home))) {
throw new BadRequestException("文件只能上传在opt目录或者home目录 ");
}
if (!(resources.getDeployPath().startsWith(opt) || resources.getDeployPath().startsWith(home))) {
throw new BadRequestException("文件只能部署在opt目录或者home目录 ");
}
if (!(resources.getBackupPath().startsWith(opt) || resources.getBackupPath().startsWith(home))) {
throw new BadRequestException("文件只能备份在opt目录或者home目录 ");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Set<Long> ids) {
for (Long id : ids) {
appRepository.deleteById(id);
}
}
@OverrideView on GitHub (pinned to 55fbf70595)
Solutions
- Change uploadPath to a directory under /opt or /home (e.g. /opt/eladmin/upload) and resubmit.
- Create that directory on the target server and give the service user write permission.
- If another root is mandatory, extend verification() (and its deploy/backup siblings) to accept an explicit configured whitelist — treat as a security change, review it.
- Ensure the path starts with a leading '/' — relative paths fail the check.
Example fix
// before
app.setUploadPath("/var/upload"); // -> 400
// after
app.setUploadPath("/opt/eladmin/upload"); Defensive patterns
Strategy: validation
Validate before calling
// Validate the path against the server whitelist before submit
String upload = form.getUploadPath();
if (upload == null || !(upload.startsWith("/opt") || upload.startsWith("/home"))) {
throw new IllegalArgumentException("uploadPath must be under /opt or /home");
}
appService.create(form); Type guard
boolean isWhitelistedPath(String p) {
return p != null && (p.startsWith("/opt") || p.startsWith("/home"));
} Try / catch
try {
appService.create(app);
} catch (BadRequestException e) {
if (e.getMessage().contains("只能上传在")) { showPathRuleError("uploadPath"); return; }
throw e;
} Prevention
- Standardize on one whitelisted root (e.g. /opt/<team>) for all App paths.
- Add a leading-slash check in the UI form; relative paths always fail.
- Pre-create the directories with correct ownership before registering the App.
When it happens
Trigger: POST/PUT /api/app with uploadPath like '/tmp/pkg', 'D:\deploy', '/var/www/upload', or 'root/...' — any path not starting with the literal prefixes '/opt' or '/home'. Note '/opt123' would pass (startsWith), while 'opt/app' (no leading slash) fails.
Common situations: Migrating configs from servers using /var or /data; Windows-style paths in dev; missing leading slash typos; security hardening reviews testing whether arbitrary paths are accepted.
Related errors
AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14).
Data as JSON: /api/errors/007c48999e755253.
Report an issue: GitHub.