@@ -2,6 +2,7 @@ package main
22
33import (
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+
250257func strategyList (strats []strategy ) string {
251258 var ids []string
252259 for _ , s := range strats {
0 commit comments