fix: enforce server trust boundaries

This commit is contained in:
2026-08-05 11:42:35 +02:00
parent 96fe5bfa79
commit a94affd6ac
10 changed files with 511 additions and 40 deletions
+8 -1
View File
@@ -172,7 +172,14 @@ func writeRemovalTargets(outputWriter io.Writer, project string, targets []serve
}
func serverOperationFailure(stderr io.Writer, err error, secretValues []string) int {
fmt.Fprintf(stderr, "thothctl: %s\n", output.Sanitize(err.Error(), secretValues))
message := output.Sanitize(err.Error(), secretValues)
var operationErr *serverops.OperationError
if errors.As(err, &operationErr) && operationErr.Detail() != "" {
detail := output.Sanitize(operationErr.Detail(), secretValues)
fmt.Fprintf(stderr, "thothctl: %s: %s\n", message, detail)
} else {
fmt.Fprintf(stderr, "thothctl: %s\n", message)
}
if errors.Is(err, serverops.ErrConfirmationRequired) || errors.Is(err, serverops.ErrUnsafeState) {
return 2
}
+45 -1
View File
@@ -104,6 +104,36 @@ func TestRunSessionsMigrateRequiresExplicitConfirmationBeforeDocker(t *testing.T
assertDockerNotInvoked(t, fixture)
}
func TestRunSessionsMigrateReportsSanitizedStageAndExitClass(t *testing.T) {
fixture := newCLIFixture(t, "MIGRATION_PASSWORD_FILE=%s\n")
fixture.setProfile(t, "server")
secretPath := filepath.Join(fixture.root, "migration-password")
if err := os.WriteFile(secretPath, []byte("migration-secret-value"), 0o600); err != nil {
t.Fatal(err)
}
fixture.setEnvironment(t, secretPath)
t.Setenv("THOTHCTL_FAKE_CONFIG", `{"services":{"core":{"image":"thothii-core:local"},"session-migrate":{"image":"thothii-core:local"}}}`)
t.Setenv("THOTHCTL_FAKE_MIGRATION_FAILURE", "TLS rejected migration-secret-value")
t.Setenv("THOTHCTL_FAKE_MIGRATION_EXIT", "23")
var stdout, stderr bytes.Buffer
code := run(context.Background(), []string{
"--installation", fixture.installationPath, "sessions", "migrate", "--yes",
}, &stdout, &stderr)
if code != 1 {
t.Fatalf("exit = %d, stderr = %q", code, stderr.String())
}
for _, required := range []string{"stage=session-migration", "class=nonzero-exit", "TLS rejected [REDACTED]"} {
if !strings.Contains(stderr.String(), required) {
t.Errorf("stderr = %q, missing %q", stderr.String(), required)
}
}
if strings.Contains(stderr.String(), "migration-secret-value") {
t.Fatalf("stderr exposed secret: %q", stderr.String())
}
}
func TestRunRemoveDisplaysExactInstallationTargetsBeforeConfirmation(t *testing.T) {
fixture := newCLIFixture(t, "")
fixture.setProfile(t, "server")
@@ -660,7 +690,18 @@ printf '%s\n' "$@" >> "$THOTHCTL_FAKE_ARGS"
printf '%s\n' -- >> "$THOTHCTL_FAKE_ARGS"
case " $* " in
*" ps --all --format json core frontend "*) printf '%s\n' "${THOTHCTL_FAKE_STOPPED_PS:-[]}" ;;
*" config --format json "*) printf '%s\n' '{"volumes":{"settings":{}},"services":{"core":{"image":"thothii-core:local","environment":{"THT_LLM_URL":"https://llm.example.invalid"}}}}' ;;
*" config --format json "*)
if [ -n "${THOTHCTL_FAKE_CONFIG:-}" ]; then
printf '%s\n' "$THOTHCTL_FAKE_CONFIG"
else
printf '%s\n' '{"volumes":{"settings":{}},"services":{"core":{"image":"thothii-core:local","environment":{"THT_LLM_URL":"https://llm.example.invalid"}}}}'
fi ;;
*" run --rm --no-deps --no-TTY session-migrate "*)
if [ "${THOTHCTL_FAKE_MIGRATION_EXIT:-0}" -ne 0 ]; then
printf '%s\n' "$THOTHCTL_FAKE_MIGRATION_FAILURE" >&2
exit "$THOTHCTL_FAKE_MIGRATION_EXIT"
fi
printf '%s\n' '{"applied":[],"drifted":[],"pending":[]}' ;;
*" ps --format json "*) printf '%s\n' '[{"Service":"core","State":"running","Health":"healthy"},{"Service":"frontend","State":"running","Health":"healthy"}]' ;;
*"io.thothii.pi.version"*) printf '%s\n' '0.80.3' ;;
*"PI_VERSION"*) printf '%s\n' '0.80.3' ;;
@@ -707,6 +748,9 @@ func (f cliFixture) setEnvContents(t *testing.T, env string) {
t.Setenv("THOTHCTL_FAKE_FAILURE", "")
t.Setenv("THOTHCTL_FAKE_FAIL_ON", "")
t.Setenv("THOTHCTL_FAKE_STOPPED_PS", "[]")
t.Setenv("THOTHCTL_FAKE_CONFIG", "")
t.Setenv("THOTHCTL_FAKE_MIGRATION_FAILURE", "")
t.Setenv("THOTHCTL_FAKE_MIGRATION_EXIT", "0")
}
func (f cliFixture) setProfile(t *testing.T, profile string) {