mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-18 14:13:34 +00:00
fix(exec): allow uploaded files in active workspaces (#748)
Shell-aware command parsing, dynamic workspace exemptions, and symlink canonicalization for exec path denial. Fixes #739.
This commit is contained in:
1 parent
e9155e0c5d
commit
8730a90acb
9 files changed
+990
-49
No files matched your search
@@ -0,0 +1,25 @@
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths
|
||||
2026/04/07 21:24:13 INFO memory + knowledge graph tools registered (PG-backed)
|
||||
2026/04/07 21:24:13 INFO web_search tool enabled
|
||||
2026/04/07 21:24:13 INFO web_fetch tool enabled policy="" blocked=0
|
||||
2026/04/07 21:24:13 INFO tts enabled provider=edge auto=off
|
||||
2026/04/07 21:24:13 INFO tool rate limiting enabled per_hour=150
|
||||
2026/04/07 21:24:13 INFO exec approval enabled security=full ask=off
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/personal_workspace_prefixed_uploads_allowed
|
||||
2026/04/07 21:24:13 WARN secure_cli.lookup: store is nil, skipping credentialed exec command="printf '%s' file=@\"/var/folders/t9/0cyfylls7d1gdy_6qp8kn2qc0000gn/T/TestSetupToolRegistryExecWorkspacePaths3385685647/001/personal/.uploads/Quarterly Report.png\""
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/team_workspace_quoted_input_allowed
|
||||
2026/04/07 21:24:13 WARN secure_cli.lookup: store is nil, skipping credentialed exec command="printf '%s' --input=\"/var/folders/t9/0cyfylls7d1gdy_6qp8kn2qc0000gn/T/TestSetupToolRegistryExecWorkspacePaths3385685647/001/teams/team-123/Quarterly Report.png\""
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/legacy_dotgoclaw_uploads_layout_allowed
|
||||
2026/04/07 21:24:13 WARN secure_cli.lookup: store is nil, skipping credentialed exec command="cp \"/var/folders/t9/0cyfylls7d1gdy_6qp8kn2qc0000gn/T/TestSetupToolRegistryExecWorkspacePaths3385685647/001/.goclaw/goclaw-workspace/ws/system/uploads/Quarterly Report.png\" \"/var/folders/t9/0cyfylls7d1gdy_6qp8kn2qc0000gn/T/TestSetupToolRegistryExecWorkspacePaths3385685647/002/partner.png\""
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/team_workspace_symlink_escape_denied
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/unrelated_data_dir_path_denied
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/workspace_local_dotgoclaw_denied
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths (0.02s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/personal_workspace_prefixed_uploads_allowed (0.01s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/team_workspace_quoted_input_allowed (0.00s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/legacy_dotgoclaw_uploads_layout_allowed (0.01s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/team_workspace_symlink_escape_denied (0.00s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/unrelated_data_dir_path_denied (0.00s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/workspace_local_dotgoclaw_denied (0.00s)
|
||||
PASS
|
||||
ok github.com/nextlevelbuilder/goclaw/cmd 0.041s
|
||||
@@ -0,0 +1,94 @@
|
||||
go: downloading github.com/golang-migrate/migrate/v4 v4.19.1
|
||||
go: downloading github.com/jackc/pgx/v5 v5.6.0
|
||||
go: downloading github.com/google/uuid v1.6.0
|
||||
go: downloading github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
|
||||
go: downloading github.com/charmbracelet/huh v0.8.0
|
||||
go: downloading github.com/spf13/cobra v1.10.2
|
||||
go: downloading github.com/bwmarrin/discordgo v0.29.0
|
||||
go: downloading golang.org/x/sync v0.19.0
|
||||
go: downloading github.com/slack-go/slack v0.19.0
|
||||
go: downloading github.com/mattn/go-runewidth v0.0.16
|
||||
go: downloading github.com/mymmrac/telego v1.6.0
|
||||
go: downloading github.com/fsnotify/fsnotify v1.9.0
|
||||
go: downloading github.com/titanous/json5 v1.0.0
|
||||
go: downloading github.com/disintegration/imaging v1.6.2
|
||||
go: downloading golang.org/x/image v0.27.0
|
||||
go: downloading golang.org/x/time v0.14.0
|
||||
go: downloading github.com/mark3labs/mcp-go v0.44.0
|
||||
go: downloading github.com/adhocore/gronx v1.19.6
|
||||
go: downloading github.com/go-rod/rod v0.116.2
|
||||
go: downloading github.com/lib/pq v1.10.9
|
||||
go: downloading github.com/mattn/go-shellwords v1.0.12
|
||||
go: downloading golang.org/x/net v0.49.0
|
||||
go: downloading golang.org/x/text v0.33.0
|
||||
go: downloading github.com/rivo/uniseg v0.4.7
|
||||
go: downloading github.com/catppuccin/go v0.3.0
|
||||
go: downloading github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7
|
||||
go: downloading github.com/charmbracelet/bubbletea v1.3.6
|
||||
go: downloading github.com/charmbracelet/lipgloss v1.1.0
|
||||
go: downloading github.com/charmbracelet/x/cellbuf v0.0.13
|
||||
go: downloading github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0
|
||||
go: downloading github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
go: downloading github.com/spf13/pflag v1.0.9
|
||||
go: downloading golang.org/x/crypto v0.47.0
|
||||
go: downloading golang.org/x/sys v0.42.0
|
||||
go: downloading github.com/valyala/fasthttp v1.69.0
|
||||
go: downloading github.com/invopop/jsonschema v0.13.0
|
||||
go: downloading github.com/spf13/cast v1.7.1
|
||||
go: downloading github.com/yosida95/uritemplate/v3 v3.0.2
|
||||
go: downloading github.com/dustin/go-humanize v1.0.1
|
||||
go: downloading github.com/charmbracelet/x/ansi v0.9.3
|
||||
go: downloading github.com/charmbracelet/x/term v0.2.1
|
||||
go: downloading github.com/atotto/clipboard v0.1.4
|
||||
go: downloading github.com/grbit/go-json v0.11.0
|
||||
go: downloading github.com/valyala/fastjson v1.6.7
|
||||
go: downloading github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6
|
||||
go: downloading github.com/muesli/cancelreader v0.2.2
|
||||
go: downloading github.com/muesli/termenv v0.16.0
|
||||
go: downloading github.com/wk8/go-ordered-map/v2 v2.1.8
|
||||
go: downloading github.com/ysmood/goob v0.4.0
|
||||
go: downloading github.com/ysmood/got v0.40.0
|
||||
go: downloading github.com/ysmood/gson v0.7.3
|
||||
go: downloading github.com/ysmood/fetchup v0.2.3
|
||||
go: downloading github.com/ysmood/leakless v0.9.0
|
||||
go: downloading github.com/andybalholm/brotli v1.2.0
|
||||
go: downloading github.com/klauspost/compress v1.18.2
|
||||
go: downloading github.com/valyala/bytebufferpool v1.0.0
|
||||
go: downloading github.com/jackc/pgpassfile v1.0.0
|
||||
go: downloading github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761
|
||||
go: downloading github.com/jackc/puddle/v2 v2.2.2
|
||||
go: downloading github.com/lucasb-eyer/go-colorful v1.2.0
|
||||
go: downloading github.com/bahlo/generic-list-go v0.2.0
|
||||
go: downloading github.com/buger/jsonparser v1.1.1
|
||||
go: downloading github.com/mailru/easyjson v0.7.7
|
||||
go: downloading gopkg.in/yaml.v3 v3.0.1
|
||||
go: downloading github.com/aymanbagabas/go-osc52/v2 v2.0.1
|
||||
go: downloading github.com/mattn/go-isatty v0.0.20
|
||||
go: downloading github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc
|
||||
go: downloading github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths
|
||||
2026/04/08 01:24:40 INFO memory + knowledge graph tools registered (PG-backed)
|
||||
2026/04/08 01:24:40 INFO web_search tool enabled
|
||||
2026/04/08 01:24:40 INFO web_fetch tool enabled policy="" blocked=0
|
||||
2026/04/08 01:24:40 INFO tts enabled provider=edge auto=off
|
||||
2026/04/08 01:24:40 INFO tool rate limiting enabled per_hour=150
|
||||
2026/04/08 01:24:40 INFO exec approval enabled security=full ask=off
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/personal_workspace_prefixed_uploads_allowed
|
||||
gateway_setup_exec_workspace_test.go:133: denied = true, want false; output = command denied by safety policy: matches pattern /tmp/TestSetupToolRegistryExecWorkspacePaths1657441769/001
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/team_workspace_quoted_input_allowed
|
||||
gateway_setup_exec_workspace_test.go:133: denied = true, want false; output = command denied by safety policy: matches pattern /tmp/TestSetupToolRegistryExecWorkspacePaths1657441769/001
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/legacy_dotgoclaw_uploads_layout_allowed
|
||||
gateway_setup_exec_workspace_test.go:133: denied = true, want false; output = command denied by safety policy: matches pattern /tmp/TestSetupToolRegistryExecWorkspacePaths1657441769/001
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/team_workspace_symlink_escape_denied
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/unrelated_data_dir_path_denied
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/workspace_local_dotgoclaw_denied
|
||||
--- FAIL: TestSetupToolRegistryExecWorkspacePaths (0.00s)
|
||||
--- FAIL: TestSetupToolRegistryExecWorkspacePaths/personal_workspace_prefixed_uploads_allowed (0.00s)
|
||||
--- FAIL: TestSetupToolRegistryExecWorkspacePaths/team_workspace_quoted_input_allowed (0.00s)
|
||||
--- FAIL: TestSetupToolRegistryExecWorkspacePaths/legacy_dotgoclaw_uploads_layout_allowed (0.00s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/team_workspace_symlink_escape_denied (0.00s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/unrelated_data_dir_path_denied (0.00s)
|
||||
--- PASS: TestSetupToolRegistryExecWorkspacePaths/workspace_local_dotgoclaw_denied (0.00s)
|
||||
FAIL
|
||||
FAIL github.com/nextlevelbuilder/goclaw/cmd 0.019s
|
||||
FAIL
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 183 KiB |
@@ -0,0 +1,228 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PR #748 — fix(exec): allow uploaded files in active workspaces</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0d0d0d;
|
||||
--fg: #e8e4df;
|
||||
--card: #1a1714;
|
||||
--border: #2d2923;
|
||||
--accent: #ef4444;
|
||||
--good: #22c55e;
|
||||
--muted: #8a837d;
|
||||
--code: #151210;
|
||||
}
|
||||
.light {
|
||||
--bg: #f8f6f3;
|
||||
--fg: #1a1714;
|
||||
--card: #ffffff;
|
||||
--border: #e5e0da;
|
||||
--accent: #dc2626;
|
||||
--good: #15803d;
|
||||
--muted: #6b6560;
|
||||
--code: #f3f0eb;
|
||||
}
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
padding: 2rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.theme-toggle {
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
color: var(--fg);
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
z-index: 100;
|
||||
}
|
||||
h1 { font-size: 1.5rem; margin-bottom: 0.5rem; }
|
||||
.subtitle { color: var(--muted); margin-bottom: 2rem; }
|
||||
.summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1rem; margin-bottom: 2rem; }
|
||||
.summary-card, .env, .comparison, .supporting {
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.summary-card { padding: 1rem; }
|
||||
.summary-card h3 {
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
margin-bottom: 0.5rem;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.env, .supporting, .comparison { padding: 1.25rem; margin-bottom: 1.5rem; }
|
||||
.env { color: var(--muted); font-size: 0.92rem; }
|
||||
.comparison h2, .supporting h2 {
|
||||
font-size: 1.05rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
|
||||
@media (max-width: 980px) { .grid { grid-template-columns: 1fr; } }
|
||||
.col-header {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.before { color: var(--muted); }
|
||||
.after { color: var(--accent); }
|
||||
.panel {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: var(--code);
|
||||
}
|
||||
.panel img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.terminal {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.45;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
padding: 1rem;
|
||||
min-height: 320px;
|
||||
}
|
||||
.hl-bad {
|
||||
display: inline-block;
|
||||
background: rgba(239, 68, 68, 0.14);
|
||||
border-left: 3px solid var(--accent);
|
||||
padding: 0.05rem 0.35rem;
|
||||
}
|
||||
.hl-good {
|
||||
display: inline-block;
|
||||
background: rgba(34, 197, 94, 0.14);
|
||||
border-left: 3px solid var(--good);
|
||||
padding: 0.05rem 0.35rem;
|
||||
}
|
||||
.desc {
|
||||
color: var(--muted);
|
||||
font-size: 0.88rem;
|
||||
margin-top: 0.65rem;
|
||||
}
|
||||
code {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
background: var(--code);
|
||||
padding: 0.12rem 0.32rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
ul { margin-left: 1.1rem; color: var(--muted); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<button class="theme-toggle" onclick="document.documentElement.classList.toggle('light'); this.textContent = document.documentElement.classList.contains('light') ? '● Dark' : '○ Light'">○ Light</button>
|
||||
|
||||
<h1>fix(exec): allow uploaded files in active workspaces</h1>
|
||||
<p class="subtitle">PR #748 — visual proof pack for issue #739</p>
|
||||
|
||||
<div class="summary">
|
||||
<div class="summary-card">
|
||||
<h3>Bug</h3>
|
||||
<p>Active workspace files under deny-roots were rejected by <code>exec</code> even when they belonged to the current upload/team scope.</p>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<h3>Root Cause</h3>
|
||||
<p>Path exemptions were static and non-shell-aware, so quoted, prefixed, and legacy screenshot-era upload paths still matched the deny root.</p>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<h3>Fix</h3>
|
||||
<p>Shell-aware parsing + canonical path checks now exempt the active personal <code>.uploads</code> subtree, the legacy <code>uploads</code> subtree, and the active team workspace.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="env">
|
||||
Before source: stable <code>claw:3000</code> backed by the unfixed <code>/opt/goclaw</code> deployment (<code>v2.7.1</code>). After source: temporary PR deployment on <code>claw:3001</code>, backed by <code>goclaw-pr748:local</code> built from the fixed code commit <code>83fa1342</code>. Both UI captures use fresh chats with the same user and <code>GLM thục bô</code>. Callout border marks the reviewed <code>exec</code> row.
|
||||
</div>
|
||||
|
||||
<div class="comparison">
|
||||
<h2>UI Before / After</h2>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<div class="col-header before">Before</div>
|
||||
<div class="panel">
|
||||
<img src="pr748-before-absolute-goclaw-blocked.png" alt="Before: stable claw blocks absolute .goclaw upload path">
|
||||
</div>
|
||||
<p class="desc">Stable <code>claw</code> release, fresh chat with <code>GLM thục bô</code>: the agent runs the exact absolute <code>/app/.goclaw/.../.uploads/...jpg</code> copy command and the <code>exec</code> row fails with the safety-policy <code>.goclaw/</code> denial.</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-header after">After</div>
|
||||
<div class="panel">
|
||||
<img src="pr748-after-absolute-goclaw-allowed.png" alt="After: fixed temporary claw deployment allows absolute .goclaw upload path">
|
||||
</div>
|
||||
<p class="desc">Temporary fixed deployment on <code>claw:3001</code>, fresh chat with the same agent: the same absolute <code>/app/.goclaw/.../.uploads/...jpg</code> copy command now completes successfully and returns <code>/tmp/partner-abs.png</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="comparison">
|
||||
<h2>Gateway Reproduction</h2>
|
||||
<div class="grid">
|
||||
<div>
|
||||
<div class="col-header before">Before</div>
|
||||
<div class="panel">
|
||||
<pre class="terminal">$ ssh claw 'docker run --rm -v /tmp/goclaw-739-before:/src -w /src golang:1.26 sh -lc "/usr/local/go/bin/go test ./cmd -run TestSetupToolRegistryExecWorkspacePaths -count=1 -v"'
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/personal_workspace_prefixed_uploads_allowed
|
||||
<span class="hl-bad">gateway_setup_exec_workspace_test.go:133: denied = true, want false; output = command denied by safety policy: matches pattern /tmp/TestSetupToolRegistryExecWorkspacePaths.../001</span>
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/team_workspace_quoted_input_allowed
|
||||
<span class="hl-bad">gateway_setup_exec_workspace_test.go:133: denied = true, want false; output = command denied by safety policy: matches pattern /tmp/TestSetupToolRegistryExecWorkspacePaths.../001</span>
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/legacy_dotgoclaw_uploads_layout_allowed
|
||||
<span class="hl-bad">gateway_setup_exec_workspace_test.go:133: denied = true, want false; output = command denied by safety policy: matches pattern /tmp/TestSetupToolRegistryExecWorkspacePaths.../001</span>
|
||||
FAIL</pre>
|
||||
</div>
|
||||
<p class="desc">Baseline source on <code>claw</code>: the exact gateway wiring still rejects all three representative workspace-path forms.</p>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-header after">After</div>
|
||||
<div class="panel">
|
||||
<pre class="terminal">$ go test ./cmd -run TestSetupToolRegistryExecWorkspacePaths -count=1 -v
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/personal_workspace_prefixed_uploads_allowed
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/team_workspace_quoted_input_allowed
|
||||
=== RUN TestSetupToolRegistryExecWorkspacePaths/legacy_dotgoclaw_uploads_layout_allowed
|
||||
<span class="hl-good">--- PASS: TestSetupToolRegistryExecWorkspacePaths (0.01s)</span>
|
||||
<span class="hl-good"> --- PASS: personal_workspace_prefixed_uploads_allowed</span>
|
||||
<span class="hl-good"> --- PASS: team_workspace_quoted_input_allowed</span>
|
||||
<span class="hl-good"> --- PASS: legacy_dotgoclaw_uploads_layout_allowed</span>
|
||||
PASS</pre>
|
||||
</div>
|
||||
<p class="desc">Current worktree: the same gateway path handling now passes for personal uploads, team workspace paths, and the screenshot-era legacy <code>.goclaw/.../uploads</code> layout.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="supporting">
|
||||
<h2>Supporting Live Recreation on <code>claw</code></h2>
|
||||
<div class="panel">
|
||||
<img src="claw-live-glm-thuc-bo-before.png" alt="Live claw recreation with GLM thục bô">
|
||||
</div>
|
||||
<p class="desc">
|
||||
This earlier live run documents the same production agent and workspace context on stable <code>claw</code>. The report’s primary Before/After pair above is the clean isolated proof you asked for; this screenshot is kept as supporting context for the reproduction journey.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="comparison">
|
||||
<h2>What This Proves</h2>
|
||||
<ul>
|
||||
<li>Quoted/prefixed upload arguments now survive the deny matcher when they point into the active personal <code>.uploads</code> subtree, the legacy <code>.goclaw/.../uploads</code> subtree, or the active team workspace.</li>
|
||||
<li>Symlink escapes, unrelated <code>dataDir</code> files, and workspace-local <code>.goclaw/*</code> remain denied.</li>
|
||||
<li>The visual behavior difference is now shown on two real frontends: stable <code>claw:3000</code> Before and temporary fixed <code>claw:3001</code> After, both using fresh conversations.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 230 KiB |
Reference in new issue
Block a user