diff options
| author | historia <[not public]> | 2026-09-18 20:03:13 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-18 20:03:13 -0400 |
| commit | 79764732406d6484f67d3dec045483dcb5d08c28 (patch) | |
| tree | 7a64e8581a540b97ed554f5723e2d587424ab1c6 /internal/admin/api_entity_path_test.go | |
| parent | f1e461ab6aec6b9bf056bbe2daa88a251e0f21da (diff) | |
| download | thehouseoficarus-79764732406d6484f67d3dec045483dcb5d08c28.tar.gz | |
feat: better card ascii art
Diffstat (limited to 'internal/admin/api_entity_path_test.go')
| -rw-r--r-- | internal/admin/api_entity_path_test.go | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/internal/admin/api_entity_path_test.go b/internal/admin/api_entity_path_test.go index 75fed7a..3a0f87b 100644 --- a/internal/admin/api_entity_path_test.go +++ b/internal/admin/api_entity_path_test.go @@ -56,10 +56,31 @@ func TestEntityAPICannotEscapeData(t *testing.T) { if !strings.Contains(rec.Body.String(), "error") { t.Fatalf("traversal rename id not rejected: status %d body %s", rec.Code, rec.Body.String()) } + // Traversal SOURCE id via the rename and move routes: the source is + // joined into a path too, so it must be rejected before it can move a + // file outside data/ (e.g. the server's own config.yaml). + sentinel := filepath.Join(root, "sentinel.yaml") + if err := os.WriteFile(sentinel, []byte("name: Sentinel\n"), 0o600); err != nil { + t.Fatal(err) + } + for _, tc := range []struct{ path, body string }{ + {"/api/objects/rename", `{"id":"../../sentinel","new_id":"stolen"}`}, + {"/api/objects/move", `{"id":"../../sentinel","dir":"sub"}`}, + } { + if rec := post(tc.path, tc.body); !strings.Contains(rec.Body.String(), "error") { + t.Fatalf("traversal source id not rejected at %s: status %d body %s", tc.path, rec.Code, rec.Body.String()) + } + } + if _, err := os.Stat(sentinel); err != nil { + t.Fatalf("traversal source id moved a file outside data/: %v", err) + } // Nothing may exist outside the data directory. if _, err := os.Stat(filepath.Join(root, "outside.yaml")); !os.IsNotExist(err) { t.Fatal("entity API escaped the data directory") } + if _, err := os.Stat(filepath.Join(root, "stolen.yaml")); !os.IsNotExist(err) { + t.Fatal("traversal rename escaped the data directory") + } } // TestTechModuleCreateRejectsTraversalID: POST /api/techs and /api/modules |
