Skip to content

[Bug]: Phase 3 — Memory File Permissions, Env Sanitization, Path Containment, Temp File Security (M-4, M-7, M-8, M-9) #32

@initializ-mk

Description

@initializ-mk

Component

forge-core (registry, tools, security, channels, LLM), forge-cli (commands, TUI wizard, runtime), forge-skills (skill parser, compiler, analyzer, trust)

Description

Four medium priority security hardening items identified via cross-reference with OpenClaw 2026.2.19 / 2026.2.20.

Re-verified 2026-03-12 against latest main (commit 7d2148b). Key changes from original analysis:

  • M-9 significantly downgraded: Originally assessed as "fixed". Re-verification found only 1 of 7 temp file locations is secure. Six sites use predictable naming and world-readable 0644 permissions. Now tracked here instead of "already fixed".
  • H-4 (Slack dedup) moved to Phase 2 since it was found to be fully missing, not partial.

Reference: FORGE-SECURITY-UPDATE.md — Phase 3

Steps to reproduce

M-4. Memory Files Stored with Weak Permissions

  • Files: forge-core/memory/filestore.go, forge-core/memory/vectorstore.go
  • Memory directory created with 0o755 (world-readable). Files written with 0o644:
    • filestore.go:20os.MkdirAll(dir, 0o755)
    • filestore.go:48 — daily log 0o644
    • filestore.go:95 — MEMORY.md 0o644
    • vectorstore.go:179 — index.json 0o644
  • Any local user can read agent memory, conversation history, and embeddings.

M-7. Skill Environment Override Sanitization

  • File: forge-cli/runtime/subprocess.go (lines 62–68)
  • Copies entire parent environment (os.Environ()), then appends skill-provided env vars without sanitization. A skill can set LD_PRELOAD, NODE_OPTIONS, PYTHONPATH, etc. to inject code into tool runtimes.

M-8. Plugin Path Containment

  • Files: forge-skills/local/scanner.go, forge-skills/trust/
  • Scanner uses fs.FS abstraction providing some containment, but no explicit realpath validation, no world-writable directory checks, no lstat checks to distinguish symlinks.

M-9. Temp File Naming and Permissions — Multiple Vulnerable Sites

  • Secure (1 of 7): forge-core/secrets/encrypted_file_provider.go:191 — uses os.CreateTemp() + 0600
  • Vulnerable (6 of 7):
    • forge-cli/runtime/scheduler_store.go:165s.path + ".tmp" with os.Create (predictable, default perms)
    • forge-core/runtime/memory_store.go:70fname + ".tmp" with os.Create (predictable, default perms)
    • forge-cli/cmd/channel.go:71os.OpenFile(envPath, ..., 0644) (world-readable .env)
    • forge-cli/cmd/init.go:562,828,847,866os.Create/os.OpenFile with default or 0644 perms
    • forge-cli/cmd/serve.go:203os.OpenFile(logPath, ..., 0644) (world-readable logs)
    • forge-cli/cmd/skills.go:210os.OpenFile(envPath, ..., 0o644) (world-readable .env)

Expected behavior

  • M-4: Memory directory 0o700, files 0o600 (owner-only access).
  • M-7: Dangerous env vars (LD_PRELOAD, NODE_OPTIONS, etc.) blocked with warnings.
  • M-8: Resolved paths verified within trusted root. World-writable dirs rejected.
  • M-9: All temp files use os.CreateTemp() with 0o600 permissions.

Actual behavior

  • M-4: Directory 0o755, files 0o644 — world-readable.
  • M-7: Any env var accepted without sanitization.
  • M-8: No realpath validation or permission checks on skill directories.
  • M-9: 6 of 7 locations use predictable path + ".tmp" naming and world-readable 0644 permissions.

Tasks

M-4. Memory File Permissions

  • Change directory permissions from 0o755 to 0o700 in filestore.go:20
  • Change file permissions from 0o644 to 0o600 in filestore.go:48, filestore.go:95, vectorstore.go:179
  • Add test verifying file and directory permissions after write

M-7. Environment Sanitization

  • Create blocklist: LD_PRELOAD, LD_LIBRARY_PATH, DYLD_INSERT_LIBRARIES, NODE_OPTIONS, PYTHONPATH, PYTHONSTARTUP, RUBYOPT, PERL5LIB, JAVA_TOOL_OPTIONS
  • Reject skill env overrides setting blocked variables
  • Log warnings on blocked variables
  • Add tests for blocked and allowed env vars

M-8. Path Containment

  • Call filepath.EvalSymlinks() after path discovery and verify within trusted root
  • Reject world-writable skill directories
  • Warn if dirs owned by different user (Unix)
  • Add tests for path escape and permission checks

M-9. Temp File Security

  • Replace path + ".tmp" in scheduler_store.go:165 with os.CreateTemp()
  • Replace fname + ".tmp" in memory_store.go:70 with os.CreateTemp()
  • Change 0644 to 0o600 in channel.go:71, init.go:828,847, serve.go:203, skills.go:210
  • Use os.CreateTemp() for init.go:562,866
  • Add tests verifying temp file permissions

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity vulnerability fixes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions