about summary refs log tree commit
diff options
context:
space:
mode:
-rw-r--r--ui-clone.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/ui-clone.c b/ui-clone.c
index 2c1ac3d..6ba8f36 100644
--- a/ui-clone.c
+++ b/ui-clone.c
@@ -92,17 +92,32 @@ void cgit_clone_info(void)
 
 void cgit_clone_objects(void)
 {
-        if (!ctx.qry.path) {
-                cgit_print_error_page(400, "Bad request", "Bad request");
-                return;
-        }
+        char *p;
+
+        if (!ctx.qry.path)
+                goto err;
 
         if (!strcmp(ctx.qry.path, "info/packs")) {
                 print_pack_info();
                 return;
         }
 
+        /* Avoid directory traversal by forbidding "..", but also work around
+         * other funny business by just specifying a fairly strict format. For
+         * example, now we don't have to stress out about the Cygwin port.
+         */
+        for (p = ctx.qry.path; *p; ++p) {
+                if (*p == '.' && *(p + 1) == '.')
+                        goto err;
+                if (!isalnum(*p) && *p != '/' && *p != '.' && *p != '-')
+                        goto err;
+        }
+
         send_file(git_path("objects/%s", ctx.qry.path));
+        return;
+
+err:
+        cgit_print_error_page(400, "Bad request", "Bad request");
 }
 
 void cgit_clone_head(void)