Skip to content

Security: GOG_ENABLE_COMMANDS lacks sub-command granularity for agent/MCP mode #290

@joshuayoes

Description

@joshuayoes

Summary

The GOG_ENABLE_COMMANDS / --enable-commands mechanism only checks the top-level command name, with no sub-command granularity. Enabling gmail allows all sub-commands including destructive ones like gmail send, gmail filters create --forward, and gmail delegates add.

Related to #220 (prompt injection / --safe flag) — this issue focuses specifically on the command-restriction surface for agent/MCP mode.

Affected Files

  • internal/cmd/enabled_commands.go

Current Code

func enforceEnabledCommands(kctx *kong.Context, enabled string) error {
    // ...
    cmd := strings.Fields(kctx.Command())
    if len(cmd) == 0 {
        return nil
    }
    top := strings.ToLower(cmd[0])  // Only checks top-level command!
    if !allow[top] {
        return usagef("command %q is not enabled", top)
    }
    return nil
}

The check at line 25-26 only inspects cmd[0] (the top-level command). Setting --enable-commands=gmail enables:

  • gmail read (safe)
  • gmail search (safe)
  • gmail send (destructive — sends email as the user)
  • gmail filters create --forward (destructive — silently redirects email)
  • gmail delegates add (destructive — grants mailbox access)

Risk

In agent/MCP mode, an LLM agent that is granted gmail access for reading emails can also send emails, create forwarding filters, and add delegates — all without the operator's intent.

Remediation

Support dotted sub-command paths in --enable-commands:

--enable-commands="gmail.read,gmail.search,gmail.list,drive.ls,drive.get"

Implementation sketch:

func enforceEnabledCommands(kctx *kong.Context, enabled string) error {
    // ...
    cmd := strings.Fields(kctx.Command())
    fullPath := strings.ToLower(strings.Join(cmd, "."))
    
    // Check from most specific to least specific
    for i := len(cmd); i > 0; i-- {
        check := strings.ToLower(strings.Join(cmd[:i], "."))
        if allow[check] {
            return nil
        }
    }
    return usagef("command %q is not enabled", fullPath)
}

This is backward-compatible: --enable-commands=gmail still allows all gmail sub-commands, but operators can now restrict to gmail.read,gmail.search for read-only access.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions