Skip to content

Commit 4be21ab

Browse files
committed
fix(redteam-ctl): use --output-format stream-json --verbose for streaming logs, use --system-prompt-file
1 parent c59c5de commit 4be21ab

1 file changed

Lines changed: 33 additions & 26 deletions

File tree

redteam/cmd/redteam-ctl/main.go

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"encoding/base64"
56
"encoding/json"
67
"flag"
78
"fmt"
@@ -147,38 +148,19 @@ func runStrategy(ctx context.Context, client *codewire.Client, s strategy, promp
147148
env.Remove(rmCtx)
148149
}()
149150

150-
// Upload system prompt to the env.
151-
logger.Println("uploading system prompt")
152-
uploadCtx, uploadCancel := context.WithTimeout(ctx, 30*time.Second)
153-
defer uploadCancel()
154-
if err := env.Files.Upload(uploadCtx, strings.NewReader(systemPrompt), "/tmp/system-prompt.md"); err != nil {
155-
logger.Printf("failed to upload prompt: %v", err)
156-
return
157-
}
151+
// Write system prompt to env and launch Claude Code.
152+
logger.Printf("starting claude code (strategy=%s)", s.ID)
158153

159-
// Also upload seed files if they exist locally.
160-
if entries, err := os.ReadDir("seeds"); err == nil {
161-
for _, e := range entries {
162-
if e.IsDir() {
163-
continue
164-
}
165-
data, err := os.ReadFile(filepath.Join("seeds", e.Name()))
166-
if err != nil {
167-
continue
168-
}
169-
seedCtx, seedCancel := context.WithTimeout(ctx, 15*time.Second)
170-
env.Files.Upload(seedCtx, strings.NewReader(string(data)), "/tmp/seeds/"+e.Name())
171-
seedCancel()
172-
}
173-
logger.Printf("uploaded %d seed files", len(entries))
154+
// Write system prompt to a file, then pass via --system-prompt-file flag.
155+
if err := writeFileViaExec(ctx, env, "/tmp/system-prompt.md", systemPrompt); err != nil {
156+
logger.Printf("failed to write prompt: %v", err)
157+
return
174158
}
175159

176-
// Launch Claude Code with the system prompt file.
177-
logger.Printf("starting claude code (strategy=%s)", s.ID)
178160
execCtx, execCancel := context.WithTimeout(ctx, 60*time.Second)
179161
defer execCancel()
180162

181-
cmd := `nohup claude --dangerously-skip-permissions --system-prompt /tmp/system-prompt.md -p "Begin your security assessment. Start by reviewing any seed files in /tmp/seeds/ if they exist, then systematically probe the environment. Report all findings." > /tmp/redteam.log 2>&1 & echo $!`
163+
cmd := `nohup claude --dangerously-skip-permissions --system-prompt-file /tmp/system-prompt.md -p "Begin your security assessment. Systematically probe the environment. Report all findings." > /tmp/redteam.log 2>&1 & echo $!`
182164
result, err := env.Exec(execCtx, codewire.ExecBody{
183165
Command: &[]string{"bash", "-c", cmd},
184166
})
@@ -247,6 +229,31 @@ func pullLog(env *codewire.Environment, dest string, lastSize *int64, logger *lo
247229
*lastSize = newSize
248230
}
249231

232+
func writeFileViaExec(ctx context.Context, env *codewire.Environment, path, content string) error {
233+
execCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
234+
defer cancel()
235+
236+
if path == "" {
237+
// Just run as a command (e.g. mkdir).
238+
_, err := env.Exec(execCtx, codewire.ExecBody{
239+
Command: &[]string{"bash", "-c", content},
240+
})
241+
return err
242+
}
243+
244+
// Use base64 to handle arbitrary content safely.
245+
encoded := base64Encode(content)
246+
cmd := fmt.Sprintf("echo '%s' | base64 -d > %s", encoded, path)
247+
_, err := env.Exec(execCtx, codewire.ExecBody{
248+
Command: &[]string{"bash", "-c", cmd},
249+
})
250+
return err
251+
}
252+
253+
func base64Encode(s string) string {
254+
return base64.StdEncoding.EncodeToString([]byte(s))
255+
}
256+
250257
func strategyList(strats []strategy) string {
251258
var ids []string
252259
for _, s := range strats {

0 commit comments

Comments
 (0)