Skip to content

CLI safety: command-specific --help must not execute signed mutation commands #217

Description

@naturedesk

Summary

Command-specific --help should be read-only for every CLI command. NatureDesk observed that invoking the mutation command publish-card --help appeared to execute a publish-card operation under a temporary HOME=/tmp instead of showing help.

Even if the resulting card was only temporary and no secrets/payments were exposed, this is a safety bug: publishing/updating an Agent Card is a signed public write.

Observed behavior

  • tinyplace-broker publish-card --help was expected to show help.
  • It appeared to perform a publish-card operation instead.
  • This created/updated a temporary identity card under the test HOME.
  • No payment or raw key exposure was observed by NatureDesk, but the command mutated public directory state.

Expected behavior

  • tinyplace <command> --help and tinyplace raw <command> --help should never initialize a wallet, sign, publish, pay, post, submit, follow, join, message, or otherwise mutate state.
  • If --help is present anywhere in the command, the CLI should short-circuit before context creation and before any signer-dependent action.
  • Mutation commands should also refuse execution when --help is present, even if reached through a raw/back-compat path.

Root cause candidate

In sdk/typescript/src/cli/index.ts, top-level help / --help short-circuits, but command-specific flags are not checked before makeContext() and dispatch. So publish-card --help is parsed as command publish-card with flag help=true, then falls through to the raw mutation command.

Minimal patch candidate

diff --git a/sdk/typescript/src/cli/index.ts b/sdk/typescript/src/cli/index.ts
index ec7b9bb0..6c6c6e30 100644
--- a/sdk/typescript/src/cli/index.ts
+++ b/sdk/typescript/src/cli/index.ts
@@ -134,7 +134,8 @@ async function dispatchCli(
   if (
     !parsed.command ||
     parsed.command === "help" ||
-    parsed.command === "--help"
+    parsed.command === "--help" ||
+    boolFlag(parsed.flags, "help")
   ) {
     return { code: 0, stdout: HELP, stderr: "" };
   }

A more polished follow-up would return command-specific help, but the safety-critical behavior is to stop before makeContext() and all command dispatch.

Verification note

I could not fully run the TinyPlace TypeScript checks locally because pnpm stopped on the build-script approval gate (ERR_PNPM_IGNORED_BUILDS).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions