Skip to content

GITHUB_READ_ONLY=yes (or on) silently leaves read-only mode off #3747

Open

Description

@rafe-walker

Describe the bug

With the environment-variable form, GITHUB_READ_ONLY only turns read-only mode on for 1, true, TRUE or t. Other common truthy spellings (yes, on, enabled) and typos (tru) are parsed as false, so the server starts with every write tool of the default toolsets exposed (46 tools instead of 27, including merge_pull_request and delete_file). The only sign is the INFO startup line readOnly=false.

GITHUB_LOCKDOWN_MODE behaves the same way.

The flag form fails closed: --read-only=yes exits with invalid argument "yes" for "--read-only" flag: strconv.ParseBool: parsing "yes": invalid syntax. So the same mistake is caught on the command line but silently ignored in the environment, which is the form most MCP client configs use. Because this is the switch people rely on to keep write tools away from an agent, failing open seems worth fixing.

Affected version

v2.1.0 (ghcr.io/github/github-mcp-server:v2.1.0, digest sha256:f6056fc10bfffcc8c81a6417a2e9ca12808647e8dd6049642a4feaadee0e0f8a; startup log shows version=v2.1.0)

Steps to reproduce the behavior

  1. docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN=<token> -e GITHUB_READ_ONLY=yes ghcr.io/github/github-mcp-server:v2.1.0 stdio
  2. Send initialize, notifications/initialized, then tools/list.
  3. 46 tools are listed, including merge_pull_request and delete_file. With GITHUB_READ_ONLY=1 the same command lists 27 read-only tools.

Results for each value I tried:

GITHUB_READ_ONLY tools write tools exposed
1, true 27 no
yes, on, enabled, tru 46 yes

Expected vs actual behavior

Expected: an unrecognised value is rejected at startup (like the --read-only flag already does), or at least logged as a warning, rather than silently disabling read-only mode.

Actual: read-only mode is silently off; only an INFO line reports readOnly=false.

Suggestion: validate GITHUB_READ_ONLY / GITHUB_LOCKDOWN_MODE with the same strict parsing as the flags and exit on an invalid value; or accept the common truthy spellings; and emit a WARN when read-only is off because a value wasn't recognised.

Logs

level=INFO msg="starting server" version=v2.1.0 host="" readOnly=false lockdownEnabled=false

Found during an independent, AI-assisted review of v2.1.0, run against a throwaway org I own; reproduced by hand.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions