diff --git a/src/kernel_services/ast_queries/file.ml b/src/kernel_services/ast_queries/file.ml
index 8378c48b20a8d8a50015aae135dca2a72b1fddca..b1222fd06eb5eadf76edca20518799aaea2672b4 100644
--- a/src/kernel_services/ast_queries/file.ml
+++ b/src/kernel_services/ast_queries/file.ml
@@ -535,8 +535,9 @@ let build_cpp_cmd = function
            for a given path. 'getcwd' always resolves them, but if the user
            supplies a path with symbolic links, this may cause issues.
            Instead of forcing the user to always provide resolved paths, we
-           currently choose to never resolve them. *)
-        let cwd = Unix.getenv "PWD" in
+           currently choose to never resolve them.
+           We only resort to getcwd() to avoid issues when PWD does not exist. *)
+        let cwd = try Unix.getenv "PWD" with Not_found -> Sys.getcwd () in
         if cwd <> dir then
           "cd " ^ dir ^ " && " ^ cpp_command
         else cpp_command
diff --git a/src/libraries/utils/filepath.ml b/src/libraries/utils/filepath.ml
index 6f1a5cb5e270e4a40a183ed8c013e4607534e3de..288780367b18439119b68204c466287417ae33e9 100644
--- a/src/libraries/utils/filepath.ml
+++ b/src/libraries/utils/filepath.ml
@@ -130,8 +130,10 @@ let insert base path_name =
    for a given path. 'getcwd' always resolves them, but if the user
    supplies a path with symbolic links, this may cause issues.
    Instead of forcing the user to always provide resolved paths, we
-   currently choose to never resolve them. *)
-let cwd = insert dummy (Sys.getenv "PWD")
+   currently choose to never resolve them.
+   Note that, in rare situations (e.g. some Docker images), PWD does not
+   exist in the environment, so in that case, we fallback to Sys.getcwd. *)
+let cwd = insert dummy (try Sys.getenv "PWD" with Not_found -> Sys.getcwd ())
 
 type existence =
   | Must_exist
diff --git a/src/plugins/markdown-report/sarif_gen.ml b/src/plugins/markdown-report/sarif_gen.ml
index 52d493fe3f97bbc0da6dc96fa8348af2fc778771..98be05d0f7718862b8c25adbf0768a699c54694a 100644
--- a/src/plugins/markdown-report/sarif_gen.ml
+++ b/src/plugins/markdown-report/sarif_gen.ml
@@ -261,8 +261,10 @@ let gen_run remarks =
      'getcwd' always resolves them, but if the user supplies a path with
      symbolic links, this may cause issues.
      Instead of forcing the user to always provide resolved paths, we
-     currently choose to never resolve them. *)
-  let uriBases = ("PWD", Sys.getenv "PWD") :: symbolicDirs in
+     currently choose to never resolve them.
+     We only resort to getcwd() to avoid issues when PWD does not exist. *)
+  let pwd = try Sys.getenv "PWD" with Not_found -> Sys.getcwd () in
+  let uriBases = ("PWD", pwd) :: symbolicDirs in
   let uriBasesJson =
     List.fold_left (fun acc (name, dir) ->
         let baseUri =
diff --git a/src/plugins/wp/wp_parameters.ml b/src/plugins/wp/wp_parameters.ml
index 8ec961641c448e59acd628407ce46e54f2ea59a5..042f73ad14869b3a275bf69fb951b86f49ba131d 100644
--- a/src/plugins/wp/wp_parameters.ml
+++ b/src/plugins/wp/wp_parameters.ml
@@ -1242,8 +1242,10 @@ let get_output_dir d =
    for a given path. 'getcwd' always resolves them, but if the user
    supplies a path with symbolic links, this may cause issues.
    Instead of forcing the user to always provide resolved paths, we
-   currently choose to never resolve them. *)
-let default = Sys.getenv "PWD" ^ "/.frama-c"
+   currently choose to never resolve them.
+   We only resort to getcwd() to avoid issues when PWD does not exist. *)
+let default =
+  (try Sys.getenv "PWD" with Not_found -> Sys.getcwd ()) ^ "/.frama-c"
 
 let has_session () =
   Session.is_set () ||