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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions