MHSanaei/3x-ui · error
invalid filename
Error message
invalid filename
What it means
ServerController.getDb (database download) builds the attachment filename from serverService.BackupFilename(c.Request.Host) and re-validates it against the package-level filenameRegex before setting Content-Disposition; a mismatch aborts with 400 'invalid filename'. Because the filename is derived from the Host header (and date/db engine), a failure means the Host header produced characters outside the safe pattern — this is a defense against header injection via Host.
Source
Thrown at internal/web/controller/server.go:343
configJson, err := a.serverService.GetConfigJson()
if err != nil {
jsonMsg(c, I18nWeb(c, "pages.index.getConfigError"), err)
return
}
jsonObj(c, configJson, nil)
}
// getDb downloads the database file.
func (a *ServerController) getDb(c *gin.Context) {
db, err := a.serverService.GetDb()
if err != nil {
jsonMsg(c, I18nWeb(c, "pages.index.getDatabaseError"), err)
return
}
filename := a.serverService.BackupFilename(c.Request.Host)
if !filenameRegex.MatchString(filename) {
_ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("invalid filename"))
return
}
c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Disposition", "attachment; filename="+filename)
_, _ = c.Writer.Write(db)
}
// getMigration downloads a cross-engine migration file: a .dump on SQLite or a
// .db SQLite database on PostgreSQL, so the data can seed the other backend.
func (a *ServerController) getMigration(c *gin.Context) {
data, filename, err := a.serverService.GetMigration()
if err != nil {
jsonMsg(c, I18nWeb(c, "pages.index.getDatabaseError"), err)
return
}
if !filenameRegex.MatchString(filename) {
_ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("invalid filename"))View on GitHub (pinned to ad32144c42)
Solutions
- Send a clean Host header (plain hostname like panel.example.com, no port/underscore) when downloading the DB.
- Fix the reverse proxy to set proxy_set_header Host $host without extra decorations.
- Check filenameRegex in the controller's file to see exactly which characters are tolerated and adjust the Host accordingly.
Example fix
# before curl -H 'Host: panel_my.host:443' .../server/getDb # 400 invalid filename # after curl -H 'Host: panel.example.com' .../server/getDb
Defensive patterns
Strategy: validation
Validate before calling
// client side: send a clean Host
await fetch(url, { headers: { Host: 'panel.example.com' } }) // or ensure proxy forwards a clean Host
// server-side harness:
var filenameRe = regexp.MustCompile(`^[A-Za-z0-9._-]+$`)
if !filenameRe.MatchString(host) { /* reject early with clear message */ } Prevention
- Set proxy_set_header Host $host (no port decoration) in reverse proxies fronting the panel.
- Avoid underscores and Unicode in the Host used for downloads.
- If downloads 400 with 'invalid filename', check the Host header first.
When it happens
Trigger: GET the DB backup endpoint with a Host header containing characters outside filenameRegex — underscores in a raw-IP Host, port suffixes, or exotic Unicode from a proxy layer.
Common situations: Accessing the panel through a reverse proxy that forwards an odd Host (e.g. 'panel_my-host' or 'host:443' variants); requesting via curl with a crafted --resolve; older proxies appending ports.
Related errors
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/d55f50188c7b0488.
Report an issue: GitHub.