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

    Type

    No type
    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