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:20 — os.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:165 — s.path + ".tmp" with os.Create (predictable, default perms)
forge-core/runtime/memory_store.go:70 — fname + ".tmp" with os.Create (predictable, default perms)
forge-cli/cmd/channel.go:71 — os.OpenFile(envPath, ..., 0644) (world-readable .env)
forge-cli/cmd/init.go:562,828,847,866 — os.Create/os.OpenFile with default or 0644 perms
forge-cli/cmd/serve.go:203 — os.OpenFile(logPath, ..., 0644) (world-readable logs)
forge-cli/cmd/skills.go:210 — os.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
M-7. Environment Sanitization
M-8. Path Containment
M-9. Temp File Security
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.
Reference:
FORGE-SECURITY-UPDATE.md— Phase 3Steps to reproduce
M-4. Memory Files Stored with Weak Permissions
forge-core/memory/filestore.go,forge-core/memory/vectorstore.go0o755(world-readable). Files written with0o644:filestore.go:20—os.MkdirAll(dir, 0o755)filestore.go:48— daily log0o644filestore.go:95— MEMORY.md0o644vectorstore.go:179— index.json0o644M-7. Skill Environment Override Sanitization
forge-cli/runtime/subprocess.go(lines 62–68)os.Environ()), then appends skill-provided env vars without sanitization. A skill can setLD_PRELOAD,NODE_OPTIONS,PYTHONPATH, etc. to inject code into tool runtimes.M-8. Plugin Path Containment
forge-skills/local/scanner.go,forge-skills/trust/fs.FSabstraction 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
forge-core/secrets/encrypted_file_provider.go:191— usesos.CreateTemp()+0600forge-cli/runtime/scheduler_store.go:165—s.path + ".tmp"withos.Create(predictable, default perms)forge-core/runtime/memory_store.go:70—fname + ".tmp"withos.Create(predictable, default perms)forge-cli/cmd/channel.go:71—os.OpenFile(envPath, ..., 0644)(world-readable .env)forge-cli/cmd/init.go:562,828,847,866—os.Create/os.OpenFilewith default or0644permsforge-cli/cmd/serve.go:203—os.OpenFile(logPath, ..., 0644)(world-readable logs)forge-cli/cmd/skills.go:210—os.OpenFile(envPath, ..., 0o644)(world-readable .env)Expected behavior
0o700, files0o600(owner-only access).LD_PRELOAD,NODE_OPTIONS, etc.) blocked with warnings.os.CreateTemp()with0o600permissions.Actual behavior
0o755, files0o644— world-readable.path + ".tmp"naming and world-readable0644permissions.Tasks
M-4. Memory File Permissions
0o755to0o700infilestore.go:200o644to0o600infilestore.go:48,filestore.go:95,vectorstore.go:179M-7. Environment Sanitization
LD_PRELOAD,LD_LIBRARY_PATH,DYLD_INSERT_LIBRARIES,NODE_OPTIONS,PYTHONPATH,PYTHONSTARTUP,RUBYOPT,PERL5LIB,JAVA_TOOL_OPTIONSM-8. Path Containment
filepath.EvalSymlinks()after path discovery and verify within trusted rootM-9. Temp File Security
path + ".tmp"inscheduler_store.go:165withos.CreateTemp()fname + ".tmp"inmemory_store.go:70withos.CreateTemp()0644to0o600inchannel.go:71,init.go:828,847,serve.go:203,skills.go:210os.CreateTemp()forinit.go:562,866