Component
forge-cli (commands, TUI wizard, runtime), forge-plugins (channel plugins, markdown converter)
Description
Three medium priority security hardening items identified via cross-reference with OpenClaw 2026.2.19 / 2026.2.20. These reduce attack surface but are not immediately exploitable.
Re-verified 2026-03-12 against latest main (commit 7d2148b). Key changes from original analysis:
- M-11 expanded: Additional issues found — URLs in
<a href> not URL-encoded (potential javascript: XSS), codeLang in class attribute not HTML-escaped.
Reference: FORGE-SECURITY-UPDATE.md — Phase 4
Steps to reproduce
M-2. Docker Base Images Not Pinned to SHA256
- File:
forge-cli/templates/Dockerfile.tmpl
- Lines 2 and 12 use
FROM {{.Runtime.Image}} — accepts mutable tags (e.g. python:3.11-slim) without requiring SHA256 digest pinning. Tag drift can silently change the base image.
M-3. Non-Root USER Not Default in Docker
- File:
forge-cli/templates/Dockerfile.tmpl (lines 69–72)
USER agent directive is conditional on {{- if .Runtime.User}}. Not enforced by default — containers run as root unless explicitly configured, expanding blast radius of container escapes.
M-11. Markdown/Content Injection — Quote and URL Escaping
- File:
forge-plugins/channels/markdown/markdown.go (lines 238–244)
escapeHTML() escapes &, <, > but NOT " or ' — potential attribute injection.
- URLs in
<a href="$2"> (line 105) are not URL-encoded — potential javascript: XSS.
codeLang in class="language-" (line 30) is not HTML-escaped.
Expected behavior
- M-2:
Runtime.Image validated to contain @sha256: digest. Warning or failure on mutable tags.
- M-3: Non-root
USER directive is unconditional by default. Opt-out via explicit Runtime.RootUser: true.
- M-11:
escapeHTML() escapes " → " and ' → '. URLs validated. codeLang escaped.
Actual behavior
- M-2: Mutable tags accepted without warning.
- M-3: Containers run as root unless
Runtime.User is explicitly set.
- M-11: Quote characters, unvalidated URLs, and raw codeLang pass through unescaped.
Tasks
M-2. Docker Base Image SHA256 Pinning
M-3. Non-Root USER Default
M-11. Escaping and Injection Prevention
Component
forge-cli (commands, TUI wizard, runtime), forge-plugins (channel plugins, markdown converter)
Description
Three medium priority security hardening items identified via cross-reference with OpenClaw 2026.2.19 / 2026.2.20. These reduce attack surface but are not immediately exploitable.
Reference:
FORGE-SECURITY-UPDATE.md— Phase 4Steps to reproduce
M-2. Docker Base Images Not Pinned to SHA256
forge-cli/templates/Dockerfile.tmplFROM {{.Runtime.Image}}— accepts mutable tags (e.g.python:3.11-slim) without requiring SHA256 digest pinning. Tag drift can silently change the base image.M-3. Non-Root USER Not Default in Docker
forge-cli/templates/Dockerfile.tmpl(lines 69–72)USER agentdirective is conditional on{{- if .Runtime.User}}. Not enforced by default — containers run as root unless explicitly configured, expanding blast radius of container escapes.M-11. Markdown/Content Injection — Quote and URL Escaping
forge-plugins/channels/markdown/markdown.go(lines 238–244)escapeHTML()escapes&,<,>but NOT"or'— potential attribute injection.<a href="$2">(line 105) are not URL-encoded — potentialjavascript:XSS.codeLanginclass="language-"(line 30) is not HTML-escaped.Expected behavior
Runtime.Imagevalidated to contain@sha256:digest. Warning or failure on mutable tags.USERdirective is unconditional by default. Opt-out via explicitRuntime.RootUser: true.escapeHTML()escapes"→"and'→'. URLs validated.codeLangescaped.Actual behavior
Runtime.Useris explicitly set.Tasks
M-2. Docker Base Image SHA256 Pinning
Runtime.Imagecontains@sha256:digestM-3. Non-Root USER Default
USERdirective unconditional (always addappuser)Runtime.RootUser: trueconfigM-11. Escaping and Injection Prevention
"→"and'→'toescapeHTML()javascript:schemecodeLangbefore inserting into class attribute