Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanaei <ho3ein.sanaei@gmail.com>2026-02-08 00:34:06 +0300
committerMHSanaei <ho3ein.sanaei@gmail.com>2026-02-08 00:54:40 +0300
commit5bb87fd3d4142d606c3875641d7ca68aa8f1a5c4 (patch)
treeca4a899e54f103a4042ba5d742a5bb872a86afca /web/service/server.go
parent491e3f9f8bd70a35de489d6da1d10b8bac3a0851 (diff)
fix : Uncontrolled data used in path expression
Co-Authored-By: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Diffstat (limited to 'web/service/server.go')
-rw-r--r--web/service/server.go66
1 files changed, 20 insertions, 46 deletions
diff --git a/web/service/server.go b/web/service/server.go
index ec217e29..c78f7374 100644
--- a/web/service/server.go
+++ b/web/service/server.go
@@ -1056,35 +1056,23 @@ func (s *ServerService) IsValidGeofileName(filename string) bool {
}
func (s *ServerService) UpdateGeofile(fileName string) error {
- files := []struct {
+ type geofileEntry struct {
URL string
FileName string
- }{
- {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip.dat"},
- {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite.dat"},
- {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat", "geoip_IR.dat"},
- {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat", "geosite_IR.dat"},
- {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip_RU.dat"},
- {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite_RU.dat"},
+ }
+ geofileAllowlist := map[string]geofileEntry{
+ "geoip.dat": {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip.dat"},
+ "geosite.dat": {"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite.dat"},
+ "geoip_IR.dat": {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat", "geoip_IR.dat"},
+ "geosite_IR.dat": {"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat", "geosite_IR.dat"},
+ "geoip_RU.dat": {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip_RU.dat"},
+ "geosite_RU.dat": {"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite_RU.dat"},
}
// Strict allowlist check to avoid writing uncontrolled files
if fileName != "" {
- // Use the centralized validation function
- if !s.IsValidGeofileName(fileName) {
- return common.NewErrorf("Invalid geofile name: contains unsafe path characters: %s", fileName)
- }
-
- // Ensure the filename matches exactly one from our allowlist
- isAllowed := false
- for _, file := range files {
- if fileName == file.FileName {
- isAllowed = true
- break
- }
- }
- if !isAllowed {
- return common.NewErrorf("Invalid geofile name: %s not in allowlist", fileName)
+ if _, ok := geofileAllowlist[fileName]; !ok {
+ return common.NewErrorf("Invalid geofile name: %q not in allowlist", fileName)
}
}
@@ -1159,32 +1147,18 @@ func (s *ServerService) UpdateGeofile(fileName string) error {
var errorMessages []string
if fileName == "" {
- for _, file := range files {
- // Sanitize the filename from our allowlist as an extra precaution
- destPath := filepath.Join(config.GetBinFolderPath(), filepath.Base(file.FileName))
- if err := downloadFile(file.URL, destPath); err != nil {
- errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", file.FileName, err))
+ // Download all geofiles
+ for _, entry := range geofileAllowlist {
+ destPath := filepath.Join(config.GetBinFolderPath(), entry.FileName)
+ if err := downloadFile(entry.URL, destPath); err != nil {
+ errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", entry.FileName, err))
}
}
} else {
- // Use filepath.Base to ensure we only get the filename component, no path traversal
- safeName := filepath.Base(fileName)
- destPath := filepath.Join(config.GetBinFolderPath(), safeName)
-
- var fileURL string
- for _, file := range files {
- if file.FileName == fileName {
- fileURL = file.URL
- break
- }
- }
-
- if fileURL == "" {
- errorMessages = append(errorMessages, fmt.Sprintf("File '%s' not found in the list of Geofiles", fileName))
- } else {
- if err := downloadFile(fileURL, destPath); err != nil {
- errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", fileName, err))
- }
+ entry := geofileAllowlist[fileName]
+ destPath := filepath.Join(config.GetBinFolderPath(), entry.FileName)
+ if err := downloadFile(entry.URL, destPath); err != nil {
+ errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", entry.FileName, err))
}
}