Skip to content

Detached pangolin up exposes the OLM device secret in the process list (passed as argv to the elevated subprocess) #127

Description

@BYBEYER

Description

When running pangolin up in the default detached mode on Linux, the CLI re-spawns itself as an elevated subprocess and passes the OLM device credentials as command-line arguments. The secret is therefore visible to every local process/user via ps / /proc/<pid>/cmdline (which is world-readable on Linux) — twice:

  1. Transiently, in the argv of the sudo sh -c "…" wrapper, which contains the fully quoted command string including --secret.
  2. For the entire lifetime of the daemon, in the argv of the detached pangolin up client --id … --secret … process.

This happens even when the credentials come from the account store (i.e. the user never typed them): the parent loads them and re-injects them into argv. PANGOLIN_CREDENTIALS_FROM_KEYRING=1 is only a marker telling the subprocess to also fetch the session token — it does not prevent the argv exposure.

Affected code (v0.15.1)

cmd/up/client/client.go:

  • Line 327–328: credentials are appended to the subprocess args:
    cmdArgs = append(cmdArgs, "--id", olmID)
    cmdArgs = append(cmdArgs, "--secret", olmSecret)
  • Lines ~400–432: the args are baked into a shell string and run via sudo sh -c:
    shellCmd := "export PANGOLIN_SUBPROCESS=1 && "
    ...
    shellCmd += "nohup"
    for _, arg := range shellArgs {
        shellCmd += " " + fmt.Sprintf("%q", arg)
    }
    shellCmd += " >/dev/null 2>&1 &"
    ...
    procCmd = exec.Command("sudo", "sh", "-c", shellCmd)

Reproduction

$ pangolin login    # against any Pangolin server
$ pangolin up       # default detached mode, authorize sudo
$ ps -eo args | grep "pangolin up client"
/home/user/.local/bin/pangolin up client --org myorg --id abc123… --secret <PLAINTEXT SECRET> --endpoint https://…

The secret stays visible in the process list as long as the client is up. Any unprivileged local user or process can read it:

$ tr '\0' ' ' </proc/$(pgrep -f "pangolin up client")/cmdline

Impact

  • The OLM device secret leaks to all local users/processes (world-readable /proc/*/cmdline).
  • It can also end up in process-monitoring/accounting tooling, EDR logs, crash reports, or shared debugging output (ps snippets pasted into tickets/chats).
  • Combined with the endpoint (also in argv), this is enough to register/connect the device identity from elsewhere.

Suggested fix

Avoid argv for the secret entirely; any of these would work:

  1. Preferred / smallest change: when PANGOLIN_CREDENTIALS_FROM_KEYRING=1, don't pass --id/--secret at all — the subprocess already reads the account store in that path (it fetches SessionToken from accountStore.ActiveAccount() around line 557–568), so it can read OlmCredentials from the same place.
  2. Pass the credentials via stdin (e.g. a small JSON blob the subprocess reads when PANGOLIN_SUBPROCESS=1).
  3. Pass them via environment variables set through exec.Cmd.Env (not via export … inside the sh -c string, which is itself argv-visible) — /proc/<pid>/environ is owner-readable only, unlike cmdline.

For the explicit --secret flag use case, keeping the flag but also honoring an env var (e.g. PANGOLIN_OLM_SECRET) would let scripts avoid argv too.

Happy to test a fix — thanks for Pangolin!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions