Skip to content

Commit fe1595f

Browse files
Aurelioloclaude
andcommitted
fix: address CodeQL path-injection alerts and second-round review findings
- Extract hintComposeRestart helper with CodeQL-tracing comment to fix go/path-injection alerts on config.SecurePath calls in hintAfterConfigSet and runConfigUnset (both now call shared helper) - Guard post-run logsFilterHint on !logFollow to prevent duplicate emission - Make doctorAutoFix return bool; only show "run doctor again" when fixes ran Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a69057b commit fe1595f

3 files changed

Lines changed: 27 additions & 19 deletions

File tree

cli/cmd/config.go

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -304,13 +304,7 @@ func runConfigSet(cmd *cobra.Command, args []string) error {
304304
// hintAfterConfigSet emits contextual guidance after a config set operation.
305305
func hintAfterConfigSet(out *ui.UI, key, value, dataDir string) {
306306
if composeAffectingKeys[key] {
307-
// Only hint about restart if compose.yml exists (pre-init users have no stack).
308-
safeDir, secErr := config.SecurePath(dataDir)
309-
if secErr == nil {
310-
if _, statErr := os.Stat(filepath.Join(safeDir, "compose.yml")); statErr == nil {
311-
out.HintGuidance("Restart containers with 'synthorg stop && synthorg start' to apply the new value.")
312-
}
313-
}
307+
hintComposeRestart(out, dataDir, "new value")
314308
}
315309

316310
switch key {
@@ -345,6 +339,20 @@ func hintAfterConfigSet(out *ui.UI, key, value, dataDir string) {
345339
}
346340
}
347341

342+
// hintComposeRestart emits a restart hint only when compose.yml exists.
343+
// Pre-init users have no stack, so the hint would be misleading.
344+
func hintComposeRestart(out *ui.UI, dataDir, what string) {
345+
// Use config.SecurePath directly so that CodeQL can trace the
346+
// sanitization for go/path-injection.
347+
safeDir, err := config.SecurePath(dataDir)
348+
if err != nil {
349+
return
350+
}
351+
if _, statErr := os.Stat(filepath.Join(safeDir, "compose.yml")); statErr == nil {
352+
out.HintGuidance(fmt.Sprintf("Restart containers with 'synthorg stop && synthorg start' to apply the %s.", what))
353+
}
354+
}
355+
348356
// applyConfigValue validates and applies a single key=value to state.
349357
func applyConfigValue(state *config.State, key, value string) error {
350358
switch key {
@@ -502,12 +510,7 @@ func runConfigUnset(cmd *cobra.Command, args []string) error {
502510
}
503511
out.Success(fmt.Sprintf("Reset %s to default", key))
504512
if composeAffectingKeys[key] {
505-
safeDir, secErr := config.SecurePath(state.DataDir)
506-
if secErr == nil {
507-
if _, statErr := os.Stat(filepath.Join(safeDir, "compose.yml")); statErr == nil {
508-
out.HintGuidance("Restart containers with 'synthorg stop && synthorg start' to apply the default value.")
509-
}
510-
}
513+
hintComposeRestart(out, state.DataDir, "default value")
511514
}
512515
return nil
513516
}

cli/cmd/doctor.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,10 @@ func runDoctor(cmd *cobra.Command, _ []string) error {
128128
}
129129

130130
if doctorFix {
131-
doctorAutoFix(ctx, cmd, out, errOut, state, report, safeDir)
132-
out.HintGuidance("Run 'synthorg doctor' again to verify fixes.")
131+
fixed := doctorAutoFix(ctx, cmd, out, errOut, state, report, safeDir)
132+
if fixed {
133+
out.HintGuidance("Run 'synthorg doctor' again to verify fixes.")
134+
}
133135
}
134136

135137
if status != doctorHealthy && !doctorFix {
@@ -197,14 +199,14 @@ func renderDoctorFiltered(out *ui.UI, report diagnostics.Report, state config.St
197199
// then executes fixes in correct order (compose first, restart once after).
198200
// Only acts on issues matching the --checks filter. Non-fatal: prints
199201
// results but does not return errors.
200-
func doctorAutoFix(ctx context.Context, _ *cobra.Command, out, errOut *ui.UI, state config.State, report diagnostics.Report, safeDir string) {
202+
func doctorAutoFix(ctx context.Context, _ *cobra.Command, out, errOut *ui.UI, state config.State, report diagnostics.Report, safeDir string) bool {
201203
_, _ = fmt.Fprintln(out.Writer())
202204
out.Section("Auto-fix")
203205

204206
status, issues := classifyDoctor(report)
205207
if status == doctorHealthy {
206208
out.Success("All systems healthy -- nothing to fix")
207-
return
209+
return false
208210
}
209211

210212
// Phase 1: scan issues and determine needed actions.
@@ -227,7 +229,7 @@ func doctorAutoFix(ctx context.Context, _ *cobra.Command, out, errOut *ui.UI, st
227229

228230
if !needComposeFix && !needRestart && len(unfixable) == 0 {
229231
out.Success("No fixable issues in selected checks")
230-
return
232+
return false
231233
}
232234

233235
// Phase 2: execute fixes in correct order (compose before restart).
@@ -257,6 +259,7 @@ func doctorAutoFix(ctx context.Context, _ *cobra.Command, out, errOut *ui.UI, st
257259
for _, issue := range unfixable {
258260
out.HintNextStep(fmt.Sprintf("No auto-fix available for: %s", issue))
259261
}
262+
return needComposeFix || needRestart
260263
}
261264

262265
// doctorFixCompose regenerates compose.yml from the embedded template.

cli/cmd/logs.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ func runLogs(cmd *cobra.Command, args []string) error {
9494
}
9595

9696
out.HintTip("Use -f to follow log output in real time.")
97-
out.HintGuidance(logsFilterHint)
97+
if !logFollow {
98+
out.HintGuidance(logsFilterHint)
99+
}
98100
return nil
99101
}
100102

0 commit comments

Comments
 (0)