xray_log_confine_test.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package service
  2. import (
  3. "encoding/json"
  4. "path/filepath"
  5. "strings"
  6. "testing"
  7. "github.com/mhsanaei/3x-ui/v3/internal/config"
  8. "github.com/mhsanaei/3x-ui/v3/internal/util/json_util"
  9. )
  10. // A log path must never escape the log folder whatever case the key is written
  11. // in: xray-core matches JSON keys onto its struct fields case-insensitively.
  12. func TestResolveXrayLogPathsConfinesEveryKeyCase(t *testing.T) {
  13. folder := config.GetLogFolder()
  14. tests := []struct {
  15. name string
  16. in string
  17. want map[string]any
  18. }{
  19. {
  20. name: "lowercase keys",
  21. in: `{"access":"/tmp/pwn.log","error":"/tmp/pwn-err.log"}`,
  22. want: map[string]any{"access": filepath.Join(folder, "pwn.log"), "error": filepath.Join(folder, "pwn-err.log")},
  23. },
  24. {
  25. name: "capitalised keys",
  26. in: `{"Access":"/tmp/pwn.log","Error":"/tmp/pwn-err.log"}`,
  27. want: map[string]any{"access": filepath.Join(folder, "pwn.log"), "error": filepath.Join(folder, "pwn-err.log")},
  28. },
  29. {
  30. name: "upper-case keys",
  31. in: `{"ACCESS":"/tmp/pwn.log"}`,
  32. want: map[string]any{"access": filepath.Join(folder, "pwn.log")},
  33. },
  34. {
  35. name: "a variant cannot smuggle a path past a none",
  36. in: `{"access":"none","Access":"/tmp/pwn.log"}`,
  37. want: map[string]any{"access": "none"},
  38. },
  39. {
  40. name: "already confined name is left alone",
  41. in: `{"access":"none","error":"none","loglevel":"warning"}`,
  42. want: map[string]any{"access": "none", "error": "none", "loglevel": "warning"},
  43. },
  44. }
  45. for _, tt := range tests {
  46. t.Run(tt.name, func(t *testing.T) {
  47. out := resolveXrayLogPaths(json_util.RawMessage(tt.in))
  48. var got map[string]any
  49. if err := json.Unmarshal(out, &got); err != nil {
  50. t.Fatalf("unmarshal %s: %v", out, err)
  51. }
  52. if len(got) != len(tt.want) {
  53. t.Fatalf("got %v, want %v", got, tt.want)
  54. }
  55. for key, want := range tt.want {
  56. if got[key] != want {
  57. t.Fatalf("key %q: got %v, want %v", key, got[key], want)
  58. }
  59. }
  60. for key := range got {
  61. if strings.EqualFold(key, "access") && key != "access" {
  62. t.Fatalf("case variant %q survived in %v", key, got)
  63. }
  64. if strings.EqualFold(key, "error") && key != "error" {
  65. t.Fatalf("case variant %q survived in %v", key, got)
  66. }
  67. }
  68. })
  69. }
  70. }