| 1 | package agent |
| 2 | |
| 3 | import ( |
| 4 | "path/filepath" |
| 5 | "strings" |
| 6 | "testing" |
| 7 | ) |
| 8 | |
| 9 | func TestNewSessionPathKeepsUntrustedModelInOnePortableComponent(t *testing.T) { |
| 10 | for _, model := range []string{"../../outside", `..\..\outside`, "vendor/model:tag", "model\x00suffix", "model\nline", "模型-v1.2"} { |
| 11 | t.Run(model, func(t *testing.T) { |
| 12 | dir := t.TempDir() |
| 13 | path := NewSessionPath(dir, model) |
| 14 | rel, err := filepath.Rel(dir, path) |
| 15 | if err != nil || rel != filepath.Base(path) || !filepath.IsLocal(rel) { |
| 16 | t.Fatalf("model escaped session directory: %q, %v", path, err) |
| 17 | } |
| 18 | if strings.ContainsAny(rel, "<>:\"/\\|?*\x00\n\r") { |
| 19 | t.Fatalf("nonportable session filename: %q", rel) |
| 20 | } |
| 21 | if strings.ContainsAny(model, "\x00\n") && !strings.HasSuffix(rel, "-session.jsonl") { |
| 22 | t.Fatalf("invalid label did not use the safe fallback: %q", rel) |
| 23 | } |
| 24 | }) |
| 25 | } |
| 26 | } |
| 27 |