Problem
The sanitizeFilename helpers in k8s/iam/cloudflare history map slashes, backslashes, colons, glob chars, quotes, angle brackets, pipes, and spaces to _ — but they let . through. A clusterName/accountID/zone of .. (or controlled via a flag like --cluster ../../etc/passwd) resolves through filepath.Join to a path outside ~/.clanker/conversations. Sentry/Linear/Notion use the right model: a whitelist [A-Za-z0-9_-] via their safeSlug helper.
Where
internal/k8s/conversation.go:245
internal/iam/conversation.go:214
internal/cloudflare/conversation.go:219
Fix
Replace the replacer with the whitelist pattern from sentry/linear/notion safeSlug:
func safeSlug(s string) string {
out := make([]byte, 0, len(s))
for i := 0; i < len(s); i++ {
c := s[i]
switch {
case c >= 'a' && c <= 'z',
c >= 'A' && c <= 'Z',
c >= '0' && c <= '9',
c == '-' || c == '_':
out = append(out, c)
}
}
if len(out) == 0 {
return "default"
}
return string(out)
}
Better: extract into internal/convhistory.SafeSlug (separate issue) — this ticket should just port the existing one.
Acceptance criteria
- Test cases:
.. → default
../../etc/passwd → etcpasswd
my-cluster.dev → my-clusterdev
- empty →
default
- All three call sites use the same helper (consider a small shared package)
- An attempt to use
--cluster ../foo does NOT write outside ~/.clanker/
Labels
bug, security
Problem
The
sanitizeFilenamehelpers in k8s/iam/cloudflare history map slashes, backslashes, colons, glob chars, quotes, angle brackets, pipes, and spaces to_— but they let.through. A clusterName/accountID/zone of..(or controlled via a flag like--cluster ../../etc/passwd) resolves throughfilepath.Jointo a path outside~/.clanker/conversations. Sentry/Linear/Notion use the right model: a whitelist[A-Za-z0-9_-]via theirsafeSlughelper.Where
internal/k8s/conversation.go:245internal/iam/conversation.go:214internal/cloudflare/conversation.go:219Fix
Replace the replacer with the whitelist pattern from sentry/linear/notion
safeSlug:Better: extract into
internal/convhistory.SafeSlug(separate issue) — this ticket should just port the existing one.Acceptance criteria
..→default../../etc/passwd→etcpasswdmy-cluster.dev→my-clusterdevdefault--cluster ../foodoes NOT write outside~/.clanker/Labels
bug, security