Ctrl K
ComunidadGuías…

engine/hmr_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package engine

import (
	"net/http/httptest"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
)

// Path components of ".." must not escape the server root (CWE-22).
func TestHMRUpdateHandlerRejectsTraversal(t *testing.T) {
	root := t.TempDir()
	ac := &Config{serverDirOrFilename: root}

	req := httptest.NewRequest("GET", hmrUpdatePrefix+"../../etc/passwd", nil)
	w := httptest.NewRecorder()
	ac.HMRUpdateHandler(w, req)

	if w.Code != 403 {
		t.Errorf("Expected 403 for traversal attempt, got %d", w.Code)
	}
}

// A symlink in the server root pointing outside it must not be served.
func TestHMRUpdateHandlerRejectsSymlinkEscape(t *testing.T) {
	if runtime.GOOS == "windows" {
		t.Skip("Symlink creation typically requires elevated privileges on Windows")
	}

	outside := t.TempDir()
	secretPath := filepath.Join(outside, "secret.js")
	if err := os.WriteFile(secretPath, []byte("export const secret = 42;\n"), 0o600); err != nil {
		t.Fatalf("Failed writing secret file: %s", err)
	}

	root := t.TempDir()
	linkPath := filepath.Join(root, "leak.js")
	if err := os.Symlink(secretPath, linkPath); err != nil {
		t.Fatalf("Failed creating symlink: %s", err)
	}

	ac := &Config{serverDirOrFilename: root}

	req := httptest.NewRequest("GET", hmrUpdatePrefix+"leak.js", nil)
	w := httptest.NewRecorder()
	ac.HMRUpdateHandler(w, req)

	if w.Code != 403 {
		t.Errorf("Expected 403 for symlink escape, got %d (body: %s)", w.Code, w.Body.String())
	}
}

// A request with no path after the HMR prefix must return 400.
func TestHMRUpdateHandlerMissingPath(t *testing.T) {
	ac := &Config{serverDirOrFilename: t.TempDir()}

	req := httptest.NewRequest("GET", hmrUpdatePrefix, nil)
	w := httptest.NewRecorder()
	ac.HMRUpdateHandler(w, req)

	if w.Code != 400 {
		t.Errorf("Expected 400 for missing path, got %d", w.Code)
	}
}

// An absolute path supplied by the client must be refused.
func TestHMRUpdateHandlerRejectsAbsolutePath(t *testing.T) {
	ac := &Config{serverDirOrFilename: t.TempDir()}

	req := httptest.NewRequest("GET", hmrUpdatePrefix+"/etc/passwd", nil)
	w := httptest.NewRecorder()
	ac.HMRUpdateHandler(w, req)

	if w.Code != 403 {
		t.Errorf("Expected 403 for absolute path, got %d", w.Code)
	}
}

// Files that can not be hot-swapped must not be readable through this endpoint.
func TestHMRUpdateHandlerRejectsNonScriptFiles(t *testing.T) {
	root := t.TempDir()
	ac := &Config{serverDirOrFilename: root}

	for _, filename := range []string{".env", "secret.lua", "notes.txt"} {
		if err := os.WriteFile(filepath.Join(root, filename), []byte("SECRET=1"), 0o644); err != nil {
			t.Fatal(err)
		}
		req := httptest.NewRequest("GET", hmrUpdatePrefix+filename, nil)
		w := httptest.NewRecorder()
		ac.HMRUpdateHandler(w, req)

		if w.Code != 403 {
			t.Errorf("Expected 403 for %s, got %d", filename, w.Code)
		}
		if strings.Contains(w.Body.String(), "SECRET") {
			t.Errorf("The contents of %s were served", filename)
		}
	}
}