@@ -227,10 +227,19 @@ def __init__(
227227 self ._ensure_cache_directory_exists ()
228228
229229 def _ensure_cache_directory_exists (self ) -> None :
230- """Create the cache directory if it doesn't exist."""
230+ """Create the cache directory if it doesn't exist with secure permissions ."""
231231 try :
232- self ._cache_dir .mkdir (parents = True , exist_ok = True )
232+ # Create directory with secure permissions (owner read/write/execute only)
233+ self ._cache_dir .mkdir (parents = True , exist_ok = True , mode = 0o700 )
234+
235+ # Verify directory permissions (if it already existed)
236+ if not self ._unsafe_skip_file_permissions_check :
237+ self ._check_permissions (self ._cache_dir , "directory" , "0o700" )
238+
233239 logger .debug (f"Cache directory created/verified: { self ._cache_dir } " )
240+ except PermissionError :
241+ # Re-raise permission errors as-is
242+ raise
234243 except OSError as e :
235244 raise OSError (f"Failed to create cache directory { self ._cache_dir } : { e } " )
236245
@@ -256,38 +265,42 @@ def _get_crl_file_lock(self, crl_cache_file: Path) -> BaseFileLock:
256265 timeout = self ._cache_file_lock_timeout ,
257266 )
258267
259- def _check_file_permissions (self , file_path : Path ) -> None :
268+ def _check_permissions (
269+ self , path : Path , resource_type : str , expected_perms : str
270+ ) -> None :
260271 """
261- Check that the CRL cache file has secure permissions (owner-only access).
272+ Check that a CRL cache resource has secure permissions (owner-only access).
262273
263274 Note: This check is only performed on Unix-like systems. Windows file
264275 permissions work differently and are not checked.
265276
266277 Args:
267- file_path: Path to the file to check
278+ path: Path to the resource (file or directory) to check
279+ resource_type: Description of the resource type (e.g., "file", "directory")
280+ expected_perms: Description of expected permissions (e.g., "0o600 or 0o400", "0o700")
268281
269282 Raises:
270- PermissionError: If file permissions are too wide or file has wrong owner
283+ PermissionError: If resource permissions are too wide
271284 """
272285 # Skip permission checks on Windows as they work differently
273286 if IS_WINDOWS :
274287 return
275288
276289 try :
277- stat_info = file_path .stat ()
290+ stat_info = path .stat ()
278291 actual_permissions = stat .S_IMODE (stat_info .st_mode )
279292
280- # Check that file is readable/writable only by owner (0o600 or more restrictive )
293+ # Check that resource is accessible only by owner (no group/other permissions )
281294 if (
282295 actual_permissions & 0o077 != 0
283296 ): # Check if group or others have any permission
284297 raise PermissionError (
285- f"CRL cache file { file_path } has insecure permissions: { oct (actual_permissions )} . "
286- f"File must be accessible only by the owner (e.g., 0o600 or 0o400 )."
298+ f"CRL cache { resource_type } { path } has insecure permissions: { oct (actual_permissions )} . "
299+ f"{ resource_type . capitalize () } must be accessible only by the owner ({ expected_perms } )."
287300 )
288301
289302 except FileNotFoundError :
290- # File doesn't exist yet, this is fine
303+ # Resource doesn't exist yet, this is fine
291304 pass
292305
293306 def get (self , crl_url : str ) -> CRLCacheEntry | None :
@@ -308,7 +321,7 @@ def get(self, crl_url: str) -> CRLCacheEntry | None:
308321
309322 # Check file permissions before reading
310323 if not self ._unsafe_skip_file_permissions_check :
311- self ._check_file_permissions (crl_file_path )
324+ self ._check_permissions (crl_file_path , "file" , "0o600 or 0o400" )
312325 else :
313326 logger .warning (
314327 f"Skipping file permissions check for { crl_file_path } "
0 commit comments