OCI-oriented build engine
0

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-builder / fuzz / fuzz_backend.ml
2.0 kB 52 lines
1(* Fuzz the COPY/secret destination resolver for path-containment. 2 3 Invariant: for any destination path -- including ones full of "..", ".", and 4 leading "/" -- [snapshot_dst] resolves inside the snapshot root or rejects it 5 with [Invalid_argument], and materialising the resolved path never creates 6 anything outside the root. Mirrors ocaml-oci's checkout fuzz: resolve against 7 [root]/out and assert [root] afterwards holds only "out" -- a traversal that 8 escaped would leave a sibling there (tar-slip / CVE-2024-21626 class). *) 9 10open Alcobar 11module Backend = Builder.Backend 12 13(* Segments biased toward adversarial shapes: "..", ".", empty and leading-"/". *) 14let segment = choose [ const ".."; const "."; const ""; const "a"; const "etc" ] 15 16let path = 17 map 18 [ bool; list1 segment ] 19 (fun leading segs -> (if leading then "/" else "") ^ String.concat "/" segs) 20 21let counter = ref 0 22 23let test_containment p = 24 Eio_main.run @@ fun env -> 25 incr counter; 26 let cwd = Eio.Stdenv.cwd env in 27 let root = 28 Eio.Path.(cwd / "_build" / "builder-backend-fuzz" / string_of_int !counter) 29 in 30 (try Eio.Path.rmtree ~missing_ok:true root with Eio.Io _ -> ()); 31 Eio.Path.mkdirs ~exists_ok:true ~perm:0o755 root; 32 let out = Eio.Path.(root / "out") in 33 Eio.Path.mkdirs ~exists_ok:true ~perm:0o755 out; 34 (match Backend.snapshot_dst ~root:out p with 35 | exception Invalid_argument _ -> () (* rejecting an unsafe dst is fine *) 36 | dst -> ( 37 try 38 (match Eio.Path.split dst with 39 | Some (parent, _) -> Eio.Path.mkdirs ~exists_ok:true ~perm:0o755 parent 40 | None -> ()); 41 Eio.Path.save ~create:(`If_missing 0o600) dst "x" 42 with Eio.Io _ | Invalid_argument _ -> ())); 43 let entries = List.sort compare (Eio.Path.read_dir root) in 44 (try Eio.Path.rmtree ~missing_ok:true root with Eio.Io _ -> ()); 45 check (List.equal String.equal entries [ "out" ]) 46 47let suite = 48 ( "backend", 49 [ 50 test_case "dest path never escapes the snapshot root" [ path ] 51 test_containment; 52 ] )