diff --git a/ggshield/core/config/auth_config.py b/ggshield/core/config/auth_config.py index 4541f6fcf2..bf1b065a01 100644 --- a/ggshield/core/config/auth_config.py +++ b/ggshield/core/config/auth_config.py @@ -130,7 +130,7 @@ def load(cls) -> "AuthConfig": def save(self) -> None: config_path = get_auth_config_filepath() data = prepare_auth_config_dict_for_save(self.to_dict()) - save_yaml_dict(data, config_path) + save_yaml_dict(data, config_path, restricted=True) def get_instance(self, instance_name: str) -> InstanceConfig: for instance in self.instances: diff --git a/ggshield/core/config/utils.py b/ggshield/core/config/utils.py index ee2eebc1c5..e7ba608d2c 100644 --- a/ggshield/core/config/utils.py +++ b/ggshield/core/config/utils.py @@ -1,3 +1,4 @@ +import os from pathlib import Path from typing import Any, Dict, List, Literal, Optional, Set, Union, overload @@ -59,13 +60,19 @@ def load_yaml_dict(path: Union[str, Path]) -> Optional[Dict[str, Any]]: return data -def save_yaml_dict(data: Dict[str, Any], path: Union[str, Path]) -> None: +def save_yaml_dict( + data: Dict[str, Any], path: Union[str, Path], restricted: bool = False +) -> None: p = Path(path) p.parent.mkdir(parents=True, exist_ok=True) with p.open("w") as f: try: stream = yaml.dump(data, indent=2, default_flow_style=False) f.write(stream) + + if restricted: + # Restrict file permissions: read and write for owner only (600) + os.chmod(p, 0o600) except Exception as e: raise UnexpectedError(f"Failed to save config to {path}:\n{str(e)}") from e