diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 869359ff92b3699a4032db3bfd4f61c9b3e31e4f..16d156c0c2bb419d332817c11ef79e3b8c9c9338 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,5 @@
 test:php74:
-  image: bokeh_php74_with_chrome
+  image: bokeh-php-7.4-webmaster
   script:
     - bash build.sh
   except:
@@ -9,7 +9,7 @@ test:php74:
 
 
 test:php81:
-  image: bokeh_php81
+  image: bokeh-php-8.1-webmaster
   script:
     - bash build.sh
   except:
diff --git a/src/Storm/FileSystem/Disk.php b/src/Storm/FileSystem/Disk.php
index 452ad0e2f29a34bf299a607d9f88b0253bd744f8..abc2880345f37af0b40a03b4795294731239f9ea 100644
--- a/src/Storm/FileSystem/Disk.php
+++ b/src/Storm/FileSystem/Disk.php
@@ -82,13 +82,13 @@ class Storm_FileSystem_Disk extends Storm_FileSystem_Abstract {
 
 
   public function directoryNamesAt($path) {
-    if (!file_exists($path))
+    if (!file_exists($path) || !is_readable($path) )
       return [];
 
     $dirs = [];
     foreach (new DirectoryIterator($path) as $entry) {
-      if ($entry->isDir() && !$entry->isDot())
-        $dirs[$entry->getFilename()] = $entry->getFilename();
+      if ($entry->isDir() && $entry->isReadable() && !$entry->isDot())
+          $dirs[$entry->getFilename()] = $entry->getFilename();
     }
 
     asort($dirs);
@@ -97,12 +97,13 @@ class Storm_FileSystem_Disk extends Storm_FileSystem_Abstract {
 
 
   public function fileNamesAt($path) {
-    if (!file_exists($path))
+    if (!file_exists($path)
+        || !is_readable($path))
       return [];
 
     $files = [];
     foreach (new DirectoryIterator($path) as $entry) {
-      if ($entry->isFile() && !$entry->isDot())
+      if ($entry->isFile() && $entry->isReadable() && !$entry->isDot())
         $files[$entry->getFilename()] = $entry->getFilename();
     }
 
diff --git a/tests/Storm/FileSystem/DiskTest.php b/tests/Storm/FileSystem/DiskTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..699e2ca5f516e5ee60222029850f4dd805ff6d6f
--- /dev/null
+++ b/tests/Storm/FileSystem/DiskTest.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Copyright (c) 2012-2022, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+abstract class Storm_FileSystem_DiskTestCase extends PHPUnit_Framework_TestCase {
+  protected Storm_FileSystem_Disk $_fs;
+
+  public function setUp() {
+    parent::setUp();
+    $this->_fs = new Storm_FileSystem_Disk;
+  }
+}
+
+class Storm_FileSystem_DiskBasicTest extends Storm_FileSystem_DiskTestCase {
+  protected $_directory,$_subdirectory;
+  public function setUp() {
+    parent::setUp();
+    $this->_directory = uniqid();
+    $this->_subdirectory = uniqid();
+    mkdir($this->_directory);
+    mkdir($this->_directory.'/'.$this->_subdirectory);
+    $file = fopen( $this->_directory.'/testfile','c');
+    fclose($file);
+  }
+
+  public function tearDown() {
+    chmod($this->_directory.'/testfile',0700);
+    unlink($this->_directory.'/testfile');
+    chmod($this->_directory.'/'.$this->_subdirectory,0700);
+    rmdir($this->_directory.'/'.$this->_subdirectory);
+    rmdir($this->_directory);
+    parent::tearDown();
+  }
+
+
+  /** @test */
+  public function directoryNamesAtForTempShouldContainsReadableSubDirectory() {
+    $this->assertEquals([$this->_subdirectory => $this->_subdirectory],
+                        $this->_fs->directoryNamesAt($this->_directory));
+  }
+
+
+  /** @test */
+  public function fileNamesAtShouldBetestfile() {
+    $this->assertEquals(['testfile' => 'testfile'],
+                        $this->_fs->fileNamesAt($this->_directory));
+  }
+
+  /** @test */
+  public function directoryNamesTmpWithNoReadableDirectoryAtShouldBeEmpty() {
+    if (FALSE === chmod($this->_directory.'/'.$this->_subdirectory,0000))
+      $this->markTestSkipped();
+    $this->assertEmpty($this->_fs->directoryNamesAt($this->_directory));
+  }
+
+
+  /** @test */
+  public function directoryNamesAtForMytestDirectoryNotReadableShouldBeEmpty() {
+    if (FALSE === chmod($this->_directory.'/'.$this->_subdirectory,0000))
+      $this->markTestSkipped();
+    $this->assertEmpty($this->_fs->directoryNamesAt($this->_directory.'/'.$this->_subdirectory));
+  }
+
+
+  /** @test */
+  public function fileNamesAtTempForTmpDirectoryShouldBeEmpty() {
+    chmod( $this->_directory.'/testfile',0000);
+    $this->assertEmpty($this->_fs->fileNamesAt($this->_directory));
+  }
+
+
+  /** @test */
+  public function fileNamesAtForTestfileShouldBeEmpty() {
+    chmod( $this->_directory.'/testfile',0000);
+    $this->assertEmpty($this->_fs->fileNamesAt($this->_directory.'/testfile'));
+  }
+}
\ No newline at end of file