Merge PR #757: security: enforce 0600/0700 file permissions on sensitive files
Enforces owner-only permissions on files containing secrets: - config.yaml, .env → 0600 - ~/.hermes/, cron dirs → 0700 - cron jobs.json, output files → 0600 Windows-safe (all chmod calls wrapped in try/except). Inspired by openclaw v2026.3.7.
This commit is contained in:
commit
6e303def12
4 changed files with 190 additions and 6 deletions
24
cron/jobs.py
24
cron/jobs.py
|
|
@ -32,10 +32,29 @@ JOBS_FILE = CRON_DIR / "jobs.json"
|
|||
OUTPUT_DIR = CRON_DIR / "output"
|
||||
|
||||
|
||||
def _secure_dir(path: Path):
|
||||
"""Set directory to owner-only access (0700). No-op on Windows."""
|
||||
try:
|
||||
os.chmod(path, 0o700)
|
||||
except (OSError, NotImplementedError):
|
||||
pass # Windows or other platforms where chmod is not supported
|
||||
|
||||
|
||||
def _secure_file(path: Path):
|
||||
"""Set file to owner-only read/write (0600). No-op on Windows."""
|
||||
try:
|
||||
if path.exists():
|
||||
os.chmod(path, 0o600)
|
||||
except (OSError, NotImplementedError):
|
||||
pass
|
||||
|
||||
|
||||
def ensure_dirs():
|
||||
"""Ensure cron directories exist."""
|
||||
"""Ensure cron directories exist with secure permissions."""
|
||||
CRON_DIR.mkdir(parents=True, exist_ok=True)
|
||||
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
_secure_dir(CRON_DIR)
|
||||
_secure_dir(OUTPUT_DIR)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
|
@ -223,6 +242,7 @@ def save_jobs(jobs: List[Dict[str, Any]]):
|
|||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
os.replace(tmp_path, JOBS_FILE)
|
||||
_secure_file(JOBS_FILE)
|
||||
except BaseException:
|
||||
try:
|
||||
os.unlink(tmp_path)
|
||||
|
|
@ -400,11 +420,13 @@ def save_job_output(job_id: str, output: str):
|
|||
ensure_dirs()
|
||||
job_output_dir = OUTPUT_DIR / job_id
|
||||
job_output_dir.mkdir(parents=True, exist_ok=True)
|
||||
_secure_dir(job_output_dir)
|
||||
|
||||
timestamp = _hermes_now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||
output_file = job_output_dir / f"{timestamp}.md"
|
||||
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(output)
|
||||
_secure_file(output_file)
|
||||
|
||||
return output_file
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue