aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/api_entity_path_test.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-18 20:03:13 -0400
committerhistoria <[not public]>2026-09-18 20:03:13 -0400
commit79764732406d6484f67d3dec045483dcb5d08c28 (patch)
tree7a64e8581a540b97ed554f5723e2d587424ab1c6 /internal/admin/api_entity_path_test.go
parentf1e461ab6aec6b9bf056bbe2daa88a251e0f21da (diff)
downloadthehouseoficarus-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.go21
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