@@ -109,11 +109,13 @@ func runSetupOpenClawPlugin(w io.Writer, errW io.Writer) error {
109109 fmt .Fprintln (w , "✓ Set tools.exec.ask = \" off\" (Rampart now handles all decisions)" )
110110 }
111111
112- // 4b. Add rampart to plugins.allow so OpenClaw doesn't warn about unallowlisted plugins .
113- if err := addToOpenClawPluginsAllow ("rampart" ); err != nil {
112+ // 4b. Add rampart to plugins.allow. Existing plugins are preserved — we only append .
113+ if added , existing , err := addToOpenClawPluginsAllow ("rampart" ); err != nil {
114114 fmt .Fprintf (errW , "⚠ Could not update plugins.allow in openclaw.json: %v\n " , err )
115+ } else if added {
116+ fmt .Fprintf (w , "✓ Added rampart to plugins.allow (existing: %v)\n " , existing )
115117 } else {
116- fmt .Fprintln (w , "✓ Added rampart to plugins.allow" )
118+ fmt .Fprintln (w , "✓ rampart already in plugins.allow (no changes to other plugins) " )
117119 }
118120
119121 // 5. Copy openclaw.yaml policy profile.
@@ -300,39 +302,44 @@ func parseCalVer(v string) []int {
300302
301303// setOpenClawExecAsk sets tools.exec.ask in ~/.openclaw/openclaw.json.
302304// addToOpenClawPluginsAllow adds pluginID to the plugins.allow list in openclaw.json
303- // if it is not already present. This prevents OpenClaw's security audit from flagging
304- // non-allowlisted plugins .
305- func addToOpenClawPluginsAllow (pluginID string ) error {
306- home , err := os .UserHomeDir ()
307- if err != nil {
308- return err
305+ // if it is not already present. Returns (added, existingIDs, error).
306+ // NEVER removes or overwrites existing entries — only appends .
307+ func addToOpenClawPluginsAllow (pluginID string ) ( added bool , existing [] string , err error ) {
308+ home , herr := os .UserHomeDir ()
309+ if herr != nil {
310+ return false , nil , herr
309311 }
310312 configPath := filepath .Join (home , ".openclaw" , "openclaw.json" )
311- data , err := os .ReadFile (configPath )
312- if err != nil {
313- return err
313+ data , rerr := os .ReadFile (configPath )
314+ if rerr != nil {
315+ return false , nil , rerr
314316 }
315317 var cfg map [string ]any
316- if err := json .Unmarshal (data , & cfg ); err != nil {
317- return err
318+ if jerr := json .Unmarshal (data , & cfg ); jerr != nil {
319+ return false , nil , jerr
318320 }
319321 plugins , _ := cfg ["plugins" ].(map [string ]any )
320322 if plugins == nil {
321323 plugins = map [string ]any {}
322324 cfg ["plugins" ] = plugins
323325 }
324326 allowRaw , _ := plugins ["allow" ].([]any )
327+ // Collect existing string entries and check for duplicates.
325328 for _ , v := range allowRaw {
326- if s , ok := v .(string ); ok && s == pluginID {
327- return nil // already present
329+ if s , ok := v .(string ); ok {
330+ existing = append (existing , s )
331+ if s == pluginID {
332+ return false , existing , nil // already present, no change
333+ }
328334 }
329335 }
336+ // Append only — preserve all existing entries.
330337 plugins ["allow" ] = append (allowRaw , pluginID )
331- out , err := json .MarshalIndent (cfg , "" , " " )
332- if err != nil {
333- return err
338+ out , merr := json .MarshalIndent (cfg , "" , " " )
339+ if merr != nil {
340+ return false , existing , merr
334341 }
335- return os .WriteFile (configPath , out , 0o600 )
342+ return true , existing , os .WriteFile (configPath , out , 0o600 )
336343}
337344
338345func setOpenClawExecAsk (value string ) error {
0 commit comments