GopeedLab/gopeed · error
download directory is not in white list
Error message
download directory is not in white list
What it means
In Downloader.initOptions (pkg/download/downloader.go, ~1360-1389), after path placeholders are replaced, if the config has a non-empty WhiteDownloadDirs list the final opts.Path must match at least one entry via filepath.Match(dir, opts.Path), otherwise creation fails with 'download directory is not in white list'. This is a security feature confining downloads to approved directories.
Source
Thrown at pkg/download/downloader.go:1383
if err != nil {
return nil, err
}
opts.Path = storeConfig.DownloadDir
}
// Replace placeholders in download path (e.g., %year%, %month%, %day%, %date%)
opts.Path = util.ReplacePathPlaceholders(opts.Path)
// if enable white download directory, check if the download directory is in the white list
if len(d.cfg.WhiteDownloadDirs) > 0 {
inWhiteList := false
for _, dir := range d.cfg.WhiteDownloadDirs {
if match, err := filepath.Match(dir, opts.Path); match && err == nil {
inWhiteList = true
break
}
}
if !inWhiteList {
return nil, errors.New("download directory is not in white list")
}
}
return opts, nil
}
func (d *Downloader) statusMut(task *Task, fn func() (bool, error)) (bool, error) {
task.statusLock.Lock()
defer task.statusLock.Unlock()
return fn()
}
func (d *Downloader) doStart(task *Task) (err error) {
var isCreate bool
var generation uint64
isReturn, err := d.statusMut(task, func() (isReturn bool, err error) {
if task.Status == base.DownloadStatusRunning || task.Status == base.DownloadStatusDone {
isReturn = trueView on GitHub (pinned to 7b7327ffb3)
Solutions
- Set the task's opts.Path to a whitelisted directory (or leave it empty to use the configured default download dir, which is normally whitelisted)
- Fix the whitelist pattern to actually cover the path: use /data/downloads/* for one level or list each subdirectory; remember filepath.Match '*' does not cross '/'
- Verify with the same matcher before creating: filepath.Match(pattern, resolvedPath)
- For deployments, whitelist the base download directory and derive per-task subpaths under it
Example fix
// before
cfg.WhiteDownloadDirs = []string{"/srv/dl/*"}
_, err := d.CreateDirect(req, &base.Options{Path: "/srv/downloads/file.iso"}) // no match
// after
cfg.WhiteDownloadDirs = []string{"/srv/dl/*", "/srv/downloads/*"}
// or point the task inside an allowed dir:
_, err := d.CreateDirect(req, &base.Options{Path: "/srv/dl/file.iso"}) Defensive patterns
Strategy: validation
Validate before calling
func pathAllowed(whiteDirs []string, p string) bool {
for _, d := range whiteDirs {
if ok, err := filepath.Match(d, p); ok && err == nil { return true }
}
return false
}
resolved := util.ReplacePathPlaceholders(opts.Path)
if len(cfg.WhiteDownloadDirs) > 0 && !pathAllowed(cfg.WhiteDownloadDirs, resolved) {
return fmt.Errorf("path %q not in white list", resolved)
} Try / catch
taskId, err := downloader.CreateDirect(req, opts)
if err != nil && strings.Contains(err.Error(), "not in white list") {
// show config guidance: whitelist the directory or choose an allowed path
} Prevention
- Derive every task path under the whitelisted base download directory
- Whitelist entries must match filepath.Match semantics: '*' does not cross '/', no '**'
- Apply ReplacePathPlaceholders before comparing, exactly like initOptions does
When it happens
Trigger: WhiteDownloadDirs is configured (e.g. ["/data/downloads/*"]) and a task is created with opts.Path = "/etc" or any non-matching directory; the path placeholder ({temp-dir} etc. via util.ReplacePathPlaceholders) resolves to a directory outside the whitelist; pattern semantics mismatch — filepath.Match treats '*' as not crossing '/' and has no '**', so /data/* won't match /data/a/b; case/separator differences (Windows \ vs /) between config and opts.Path.
Common situations: Server deployments enabling the whitelist but clients sending absolute paths; upgrading a deployment where the whitelist was added but old clients keep their previous paths; users assuming glob '**' support; relative paths in opts.Path that never match an absolute whitelist entry.
Related errors
- script file does not exist: %s
- batch files (.bat/.cmd) are only supported on Windows
- webhook URL is empty
AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16).
Data as JSON: /api/errors/e1c6c700e0eb64e9.
Report an issue: GitHub.