-
Notifications
You must be signed in to change notification settings - Fork 2
handle sub routes #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
cmd/main.go
Outdated
|
|
||
| fs.ServeHTTP(w, r) | ||
| // Check if exact file exists (e.g., /favicon.ico, /_next/static/...) | ||
| if info, err := os.Stat(resolvedPath); err == nil && !info.IsDir() { |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression
Copilot Autofix
AI 18 days ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
cmd/main.go
Outdated
| fs.ServeHTTP(w, r) | ||
| // Check if exact file exists (e.g., /favicon.ico, /_next/static/...) | ||
| if info, err := os.Stat(resolvedPath); err == nil && !info.IsDir() { | ||
| http.ServeFile(w, r, resolvedPath) |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression
Copilot Autofix
AI 18 days ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
cmd/main.go
Outdated
| http.Error(w, "Invalid path", http.StatusBadRequest) | ||
| return | ||
| } | ||
| if info, err := os.Stat(htmlPathAbs); err == nil && !info.IsDir() { |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression
Copilot Autofix
AI 18 days ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
cmd/main.go
Outdated
| return | ||
| } | ||
| if info, err := os.Stat(htmlPathAbs); err == nil && !info.IsDir() { | ||
| http.ServeFile(w, r, htmlPathAbs) |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression
Copilot Autofix
AI 18 days ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
cmd/main.go
Outdated
| http.Error(w, "Invalid path", http.StatusBadRequest) | ||
| return | ||
| } | ||
| if info, err := os.Stat(indexPathAbs); err == nil && !info.IsDir() { |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression
Copilot Autofix
AI 18 days ago
Copilot could not generate an autofix suggestion
Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.
cmd/main.go
Outdated
| return | ||
| } | ||
| if info, err := os.Stat(indexPathAbs); err == nil && !info.IsDir() { | ||
| http.ServeFile(w, r, indexPathAbs) |
Check failure
Code scanning / CodeQL
Uncontrolled data used in path expression
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 18 days ago
In general, the problem is that a file path derived from r.URL.Path is used in http.ServeFile after only a custom validation that the analyzer does not fully trust. The fix is to (a) make the path validation clearly and robustly constrain paths to live under a configured static root, and (b) ensure every path passed to http.ServeFile or other file operations is validated using that function. This addresses real traversal risk and also helps CodeQL recognize that tainted data is sanitized before reaching the sink.
The single best fix here, without changing functionality, is:
-
Strengthen
isPathWithinRootto operate in a clearly “relative to root” manner by:- Cleaning the root path and turning it into an absolute path.
- Cleaning the candidate path, joining it to the absolute root if it is not already absolute, and then resolving that to an absolute path.
- Returning the resolved candidate only if it is equal to the root or has the root as a directory prefix (using
absRoot + string(os.PathSeparator)).
This keeps the same logical behavior (candidate must be within root) but makes the sanitizer clearer and less dependent on how the candidate was built earlier.
-
Use
isPathWithinRootfor the finalindex.htmlfallback as well, to maintain consistent protection and to make sure every served path is checked. Currently:resolvedPathis validated.htmlPathAbsandindexPathAbsare validated.- The final
indexPath := filepath.Join(staticRoot, "index.html")is used directly inhttp.ServeFilewithout validation. While this particular path is constant and safe, reusingisPathWithinRootthere tightens the pattern and can help the analyzer understand that allServeFilecalls are guarded.
Concretely:
-
In
cmd/main.go, updateisPathWithinRoot(lines 23–36) to:- Clean and absolutize the
root. - Clean the
candidate, and ifcandidateis not absolute, join it withabsRoot. - Absolutize the resulting candidate and perform the prefix check.
- Clean and absolutize the
-
Near the bottom (lines 157–159), replace the direct join and
ServeFilewith:- Compute
indexPath := filepath.Join(staticRoot, "index.html"). - Pass it through
isPathWithinRoot(staticRoot, indexPath)and handle theokflag. - Use the validated
indexPathAbsforhttp.ServeFile.
- Compute
No new imports are needed; we reuse os, filepath, and strings that are already imported.
-
Copy modified line R22 -
Copy modified line R24 -
Copy modified lines R30-R39 -
Copy modified lines R43-R44 -
Copy modified lines R162-R167
| @@ -19,17 +19,29 @@ | ||
| "github.com/tikv/client-go/v2/rawkv" | ||
| ) | ||
|
|
||
| // isPathWithinRoot returns true if candidate is the same as root or a descendant of it. | ||
| // isPathWithinRoot returns the absolute candidate path and true if it is the same as root or a descendant of it. | ||
| func isPathWithinRoot(root, candidate string) (string, bool) { | ||
| // Normalize and absolutize the root directory. | ||
| cleanRoot := filepath.Clean(root) | ||
| absRoot, err := filepath.Abs(cleanRoot) | ||
| if err != nil { | ||
| return "", false | ||
| } | ||
| absCandidate, err := filepath.Abs(candidate) | ||
|
|
||
| // Normalize the candidate path. | ||
| cleanCandidate := filepath.Clean(candidate) | ||
|
|
||
| // If candidate is not absolute, interpret it as relative to absRoot. | ||
| if !filepath.IsAbs(cleanCandidate) { | ||
| cleanCandidate = filepath.Join(absRoot, cleanCandidate) | ||
| } | ||
|
|
||
| absCandidate, err := filepath.Abs(cleanCandidate) | ||
| if err != nil { | ||
| return "", false | ||
| } | ||
|
|
||
| // Candidate must be equal to root or reside within it. | ||
| if absCandidate == absRoot || strings.HasPrefix(absCandidate, absRoot+string(os.PathSeparator)) { | ||
| return absCandidate, true | ||
| } | ||
| @@ -156,7 +159,12 @@ | ||
|
|
||
| // Default: serve index.html (home page or SPA fallback) | ||
| indexPath := filepath.Join(staticRoot, "index.html") | ||
| http.ServeFile(w, r, indexPath) | ||
| indexPathAbs, ok := isPathWithinRoot(staticRoot, indexPath) | ||
| if !ok { | ||
| http.Error(w, "Invalid path", http.StatusBadRequest) | ||
| return | ||
| } | ||
| http.ServeFile(w, r, indexPathAbs) | ||
| }) | ||
| port := os.Getenv("PORT") | ||
| if port == "" { |
54d3621 to
3fb6c6a
Compare
No description provided.