```
feat(vscode): add Daemon debug configuration Add a new debug configuration for Daemon mode in VS Code launch settings to facilitate debugging with specific environment variables and flags. fix(config): use filepath.Dir for config path resolution Change from assigning raw config path to using filepath.Dir to get the directory of the config file, ensuring proper directory handling. refactor(filehandler): improve file access security and directory handling Improve security checks by using Lstat instead of Mode check for symlinks, enhance directory handling when URL ends with "/" to prevent path traversal errors, and refine path resolution logic to properly handle root directory cases. fix(config): disable SSL and update example root path Disable SSL for teststatic server configuration and update root path from relative "./example" to "../example" for proper example directory access. ``` Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
f4a2967f59
commit
6fd9f32f9c
|
|
@ -21,6 +21,24 @@
|
|||
"showLog": true,
|
||||
"trace": "log",
|
||||
"dlvFlags": ["--check-go-version=false"]
|
||||
},
|
||||
{
|
||||
"name": "Daemon",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "${workspaceFolder}",
|
||||
"env": {
|
||||
"GODEBUG": "cgocheck=0",
|
||||
"_go_daemon": "g_daemon"
|
||||
},
|
||||
"args": [
|
||||
"run",
|
||||
"${file}"
|
||||
],
|
||||
"showLog": true,
|
||||
"trace": "log",
|
||||
"dlvFlags": ["--check-go-version=false"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -133,7 +133,7 @@ func LoadConfig() {
|
|||
server := model.HttpServerConfig{}
|
||||
err = decoder.Decode(&server)
|
||||
if err == nil {
|
||||
server.ConfPath = config
|
||||
server.ConfPath = filepath.Dir(config)
|
||||
normalizeServer(&server)
|
||||
model.Config.Servers = append(model.Config.Servers, &server)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -25,27 +25,34 @@ func (f FileHandler) String() string {
|
|||
}
|
||||
func (f FileHandler) Open(name string) (http.File, error) {
|
||||
l := gologger.GetLogger("filehandler")
|
||||
l.Debug("access:", name)
|
||||
l.Debug("Open called: name=", name)
|
||||
if strings.HasPrefix(name, "../") {
|
||||
return nil, errors.New("not permitted")
|
||||
}
|
||||
relatedPath := strings.TrimPrefix(name, f.WPath)
|
||||
|
||||
rPath := filepath.Join(f.Root, strings.TrimPrefix(relatedPath, "/"))
|
||||
l.Debug("access:", rPath)
|
||||
// When URL ends with "/" (like "/") and WPath matches, we should return
|
||||
// the directory and let http.FileServer handle the redirect to default file.
|
||||
// This prevents "http: attempting to traverse a non-directory" error.
|
||||
if relatedPath == "" && f.Default != "" {
|
||||
relatedPath = "."
|
||||
}
|
||||
|
||||
// If relatedPath becomes ".", use Root directly to represent the directory itself
|
||||
var rPath string
|
||||
if relatedPath == "." {
|
||||
rPath = f.Root
|
||||
} else {
|
||||
rPath = filepath.Join(f.Root, strings.TrimPrefix(relatedPath, "/"))
|
||||
}
|
||||
|
||||
// Resolve symlinks and clean path to prevent path traversal
|
||||
realRoot, _ := filepath.EvalSymlinks(f.Root)
|
||||
realPath, _ := filepath.EvalSymlinks(filepath.Dir(rPath))
|
||||
if realPath != realRoot && !strings.HasPrefix(realPath, realRoot+string(filepath.Separator)) {
|
||||
return nil, errors.New("not permitted")
|
||||
}
|
||||
realRPath, _ := filepath.EvalSymlinks(rPath)
|
||||
|
||||
if rPath == f.Root {
|
||||
if f.Default == "" {
|
||||
return nil, errors.New("not permit list dir")
|
||||
}
|
||||
rPath = filepath.Join(rPath, f.Default)
|
||||
// Check if the resolved path is within root
|
||||
if realRPath != realRoot && !strings.HasPrefix(realRPath, realRoot+string(filepath.Separator)) {
|
||||
return nil, errors.New("not permitted")
|
||||
}
|
||||
|
||||
fInfo, exists, err := FileExists(rPath)
|
||||
|
|
@ -57,11 +64,13 @@ func (f FileHandler) Open(name string) (http.File, error) {
|
|||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
if fInfo.IsDir() && rPath != strings.TrimSuffix(f.Root, "/") {
|
||||
// If it's a directory and not the root, don't allow listing
|
||||
if fInfo.IsDir() && rPath != f.Root {
|
||||
return nil, errors.New("not permit list dir")
|
||||
}
|
||||
|
||||
if fInfo.Mode() == fs.ModeSymlink {
|
||||
// Use Lstat to check if the path itself is a symlink (doesn't follow symlinks)
|
||||
if lstatInfo, err := os.Lstat(rPath); err == nil && lstatInfo.Mode()&fs.ModeSymlink != 0 {
|
||||
return nil, errors.New("not permit follow symbol link")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
"name": "teststatic",
|
||||
"server": ["www.teststatic.com"],
|
||||
"port": 8088,
|
||||
"enable_ssl":true,
|
||||
"enable_ssl":false,
|
||||
"paths": [
|
||||
{
|
||||
"path": "/",
|
||||
"root": "./example",
|
||||
"root": "../example",
|
||||
"default": "index.html"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue