I Tried Diagnosing GitHub Settings Against Best Practices with Microsoft's Official OSS "ghqr"
ちょっと話題の記事

I Tried Diagnosing GitHub Settings Against Best Practices with Microsoft's Official OSS "ghqr"

ghqr (GitHub Quick Review) checks 70 items at the Enterprise, Org and Repo levels and outputs remediation actions as reports in JSON, MD and Excel.
2026.05.01

This page has been translated by machine translation. View original

Operating GitHub is hard.

In many organizations, isn't someone looking after it on the side of their regular duties? Keeping up with security requirements, which grow more demanding every day, is also hard.

Here is good news for such operations teams.

Microsoft has open-sourced a Go-based CLI tool called ghqr (GitHub Quick Review) that diagnoses GitHub settings against best practices.

https://github.com/microsoft/ghqr

It evaluates settings against best practices at the Enterprise / Organization / Repository level and outputs reports in three formats: Excel / Markdown / JSON. The repository's About says "Evaluate your enterprise and organizations with GitHub best practices".

Running it takes just one command.

  • $ ghqr scan -e ENTERPRISE-NAME # Scan the entire enterprise account
  • $ ghqr scan -o ORG-NAME # Scan the entire organization

You can also easily detect Organizations that do not have two-factor authentication enabled.

It may be easy to picture it as a GitHub version of CSPM (that's slightly overselling it).

It has only just been released and its features are not yet complete, but I tried out the CLI and MCP integration, so I'll briefly introduce what kind of tool it is.

Test Environment

  • ghqr : v.0.2.1
  • Target of inspection : GitHub Organization

Supported GitHub

GitHub comes in various service forms.

ghqr supports the following cloud editions in the broad sense, hosted on github.com and ghe.com.

  • Enterprise/Organization/Repository on github.com
  • Data-residency GitHub Enterprise Cloud hosted on ghe.com

As the following issue shows, GitHub Enterprise Server (GHES = on-premises edition) is not supported at this time.

https://github.com/microsoft/ghqr/issues/66

Installation

Install from assets

https://github.com/microsoft/ghqr/releases

From the main branch

To install directly from the main branch, run the following commands.

Linux/macOS

bash -c "$(curl -fsSL https://raw.githubusercontent.com/microsoft/ghqr/main/scripts/install.sh)"

Windows

Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/microsoft/ghqr/main/scripts/install.ps1'))

We have already looked over the check items with list-recommendations. Let's go through the remaining two in order.

Only three subcommands

The ghqr CLI has only three subcommands.

  1. ghqr list-recommendations Outputs the list of recommendations
  2. ghqr scan Runs a scan
  3. ghqr mcp Starts as an MCP server

ghqr list-recommendations : List of checklist items

ghqr checks whether settings follow best practices.

You can view this checklist with the ghqr list-recommendations command.

$ ghqr -v
ghqr version v.0.2.1

$ ghqr list-recommendations
ID                  SCOPE           CATEGORY                SEVERITY    TITLE
──────────────────  ──────────────  ──────────────────────  ──────────  ─────────────────────────────────────────────────────
ent-alert-001       enterprise      dependencies            critical    Critical Dependabot alerts open across enterprise
ent-alert-002       enterprise      dependencies            high        High-severity Dependabot alerts open across enterprise
ent-alert-003       enterprise      security                high        Code scanning alerts open across enterprise
ent-alert-004       enterprise      security                critical    Secret scanning alerts open across enterprise
ent-ghas-001        enterprise      security                high        GitHub Advanced Security not enabled at enterprise level
ent-ghas-002        enterprise      security                high        Secret scanning not enabled as enterprise default
ent-ghas-003        enterprise      security                high        Secret scanning push protection not enabled as enterprise default
ent-ghas-004        enterprise      dependencies            high        Dependabot alerts not enabled as enterprise default
ent-ghas-005        enterprise      dependencies            medium      Dependabot security updates not enabled as enterprise default
ent-ghas-006        enterprise      dependencies            medium      Dependency graph not enabled as enterprise default
ent-ghas-007        enterprise      security                low         Secret scanning for non-provider patterns not enabled as enterprise default
ent-log-001         enterprise      security                critical    Suspicious audit log events detected
ent-log-002         enterprise      security                high        Audit log streaming configuration cannot be verified
org-act-001         organization    actions                 high        Default GITHUB_TOKEN permission is write
org-act-002         organization    actions                 high        GitHub Actions allows all third-party actions
org-act-003         organization    actions                 low         Actions restricted to local repositories only
org-alert-001       organization    dependencies            critical    Critical Dependabot alerts open across organization
org-alert-002       organization    dependencies            high        High-severity Dependabot alerts open across organization
org-alert-003       organization    dependencies            medium      Open Dependabot alerts across organization
org-alert-004       organization    security                high        Code scanning alerts open across organization
org-alert-005       organization    security                critical    Secret scanning alerts open across organization
org-cop-001         organization    copilot_cost            medium      Copilot seats assigned to all organization members
org-cop-002         organization    copilot_security        high        Copilot allowed to suggest code matching public repositories
org-cop-003         organization    copilot_cost            medium      High percentage of inactive Copilot seats
org-def-001         organization    dependencies            high        Dependabot alerts not enabled by default for new repositories
org-def-002         organization    dependencies            medium      Dependabot security updates not enabled by default for new repositories
org-def-003         organization    dependencies            medium      Dependency graph not enabled by default for new repositories
org-def-004         organization    security                high        Secret scanning not enabled by default for new repositories
org-def-005         organization    security                high        Secret scanning push protection not enabled by default for new repositories
org-def-006         organization    security                medium      GitHub Advanced Security not enabled by default for new repositories
org-sec-001         organization    security                high        Two-factor authentication not required
org-sec-002         organization    security                medium      Web commit signoff not required
org-sec-003         organization    access_control          high        Default repository permission set to admin
org-sec-004         organization    access_control          medium      Members can create public repositories
org-sec-005         organization    access_control          medium      No security manager team assigned
org-sec-006         organization    security                info        EMU enabled: two-factor authentication is controlled by your identity provider
repo-acc-001        repository      access_control          high        Excessive admin collaborators
repo-acc-002        repository      access_control          medium      Direct collaborators instead of teams
repo-acc-003        repository      security                high        Deploy keys with write access
repo-acc-004        repository      security                medium      Unverified deploy keys
repo-acc-005        repository      security                medium      Deploy keys present — consider GitHub Apps or OIDC
repo-bp-001         repository      branch_protection       critical    No branch protection configured on default branch
repo-bp-002         repository      branch_protection       critical    No approving reviews required before merge
repo-bp-003         repository      branch_protection       medium      Only 1 approving review required
repo-bp-004         repository      branch_protection       high        Stale reviews not dismissed on new commits
repo-bp-005         repository      branch_protection       medium      Code owner review not required
repo-bp-006         repository      branch_protection       critical    Pull request reviews not configured
repo-bp-007         repository      branch_protection       high        Strict status checks not enabled
repo-bp-008         repository      branch_protection       high        No specific status checks required
repo-bp-009         repository      branch_protection       high        No required status checks configured
repo-bp-010         repository      branch_protection       critical    Force pushes allowed on protected branch
repo-bp-011         repository      branch_protection       high        Branch deletion allowed on protected branch
repo-bp-012         repository      branch_protection       medium      Signed commits not required
repo-bp-013         repository      branch_protection       low         Linear history not required
repo-bp-014         repository      branch_protection       info        Branch protected by repository rulesets (not legacy branch protection)
repo-comm-001       repository      community               info        GitHub Discussions not enabled
repo-feat-001       repository      features                low         Issues and Discussions both disabled
repo-feat-002       repository      maintenance             low         Auto-delete branches on merge not enabled
repo-meta-001       repository      community               medium      Repository has no description
repo-meta-002       repository      community               low         Repository has no topics
repo-meta-003       repository      maintenance             low         Repository appears dormant but is not archived
repo-sec-001        repository      security                high        Dependabot alerts not enabled
repo-sec-002        repository      security                critical    Critical Dependabot alerts open
repo-sec-003        repository      security                high        High-severity Dependabot alerts open
repo-sec-004        repository      security                low         No SECURITY.md file found
repo-sec-005        repository      access_control          medium      No CODEOWNERS file found
repo-sec-006        repository      security                medium      Dependabot alerts enabled but no dependabot.yml found
repo-sec-007        repository      security                high        Dependabot not configured
repo-sec-008        repository      security                high        Code scanning (CodeQL) not configured
repo-sec-009        repository      security                info        No custom CodeQL configuration file

70 recommendation(s) shown (total in registry: 70)

Let's list the high-severity items at the Organization level.

ghqr list-recommendations --scope organization --severity high
ID                  SCOPE           CATEGORY                SEVERITY    TITLE
──────────────────  ──────────────  ──────────────────────  ──────────  ─────────────────────────────────────────────────────
org-act-001         organization    actions                 high        Default GITHUB_TOKEN permission is write
org-act-002         organization    actions                 high        GitHub Actions allows all third-party actions
org-alert-002       organization    dependencies            high        High-severity Dependabot alerts open across organization
org-alert-004       organization    security                high        Code scanning alerts open across organization
org-cop-002         organization    copilot_security        high        Copilot allowed to suggest code matching public repositories
org-def-001         organization    dependencies            high        Dependabot alerts not enabled by default for new repositories
org-def-004         organization    security                high        Secret scanning not enabled by default for new repositories
org-def-005         organization    security                high        Secret scanning push protection not enabled by default for new repositories
org-sec-001         organization    security                high        Two-factor authentication not required
org-sec-003         organization    access_control          high        Default repository permission set to admin

10 recommendation(s) shown (total in registry: 70)

Controls for these common problems are provided, such as:

  • 2FA is not required at the organization level
  • The default permission of GITHUB_TOKEN is write
  • The default repository permission is admin

ghqr scan : Run a scan

ghqr scan is the main scan command.

You specify the target with arguments.

  • ghqr scan : The broad scope the authenticated user belongs to
  • ghqr scan -e my-ent : Under a specific Enterprise
  • ghqr scan -o my-org : Under a specific Organization
  • ghqr scan -r owner/repo : A specific repository

Scanning an Organization

People interested in this kind of tool are probably often managing an Organization.

Just pass a PAT (Personal Access Token) and specify the Organization to scan, and the scan is done.

export GH_TOKEN=github_pat_xxxxxxxxxxxx
ghqr scan -o my-org

Here are the execution results.

$ ghqr scan -o my-org
2026-04-30T22:06:59+09:00 INF Scan started stages=9
2026-04-30T22:06:59+09:00 INF Initializing scan...
2026-04-30T22:06:59+09:00 INF Authenticated to GitHub user=example
2026-04-30T22:06:59+09:00 INF Skipping enterprise scan - no enterprises specified (use --enterprise or -e flag)
2026-04-30T22:06:59+09:00 INF Starting organization scan count=1
2026-04-30T22:06:59+09:00 INF Scanning organization organization=my-org
2026-04-30T22:06:59+09:00 INF Starting organization scan organization=my-org
2026-04-30T22:07:02+09:00 INF Organization scan completed organization=my-org
2026-04-30T22:07:02+09:00 INF Organization scan completed successfully organization=my-org
2026-04-30T22:07:02+09:00 INF Organization scan completed
2026-04-30T22:07:02+09:00 INF Fetching organization repository names via GraphQL org=my-org
2026-04-30T22:07:02+09:00 INF Scanning repositories in batches batch_size=5 count=4 org=my-org workers=5
2026-04-30T22:07:04+09:00 INF Enriching repositories with ruleset data via GraphQL (batched) chunks=1 org=my-org repos=3 workers=10
2026-04-30T22:07:05+09:00 INF Enriching repository current=1 repository=my-org/xx1 total=3
2026-04-30T22:07:05+09:00 INF Enriching repository current=2 repository=my-org/xx2 total=3
2026-04-30T22:07:05+09:00 INF Enriching repository current=3 repository=my-org/xx3 total=3
2026-04-30T22:07:05+09:00 INF Org repository scan complete org=my-org scanned=4
2026-04-30T22:07:05+09:00 INF Running best-practice evaluations...
2026-04-30T22:07:05+09:00 INF Evaluations completed
2026-04-30T22:07:05+09:00 INF Rendering reports... results=31
2026-04-30T22:07:05+09:00 INF JSON report written path=ghqr_20260430_220659.json
2026-04-30T22:07:05+09:00 INF Generating Excel report: ghqr_20260430_220659.xlsx
2026-04-30T22:07:05+09:00 INF Excel report written path=ghqr_20260430_220659.xlsx
2026-04-30T22:07:05+09:00 INF Markdown report written path=ghqr_20260430_220659.md
2026-04-30T22:07:05+09:00 INF Scan summary enterprises=0 organizations=1 output=ghqr_20260430_220659 repositories=4
2026-04-30T22:07:05+09:00 INF Scan completed in 6s
2026-04-30T22:07:05+09:00 INF Scan completed

When it finishes, three files with the same base name are produced.

$ ls -1
ghqr_20260430_220659.json
ghqr_20260430_220659.md
ghqr_20260430_220659.xlsx

It uses parallel processing, and even with more than 1,000 repositories the scan completed in a few minutes.

Structure of the JSON report

The JSON format is useful when you want to process the scan results.

It is easy to aggregate with jq, check differences from the previous run, or integrate with other systems.

Here is an excerpt of the beginning.

{
	"generated_at": "2026-04-30T13:07:05Z",
	"organizations": {
		"your-org": {
			"copilot": {
				"active_this_cycle": 5,
				"billing_enabled": true,
				"inactive_this_cycle": 0,
				"public_code_suggestions": "block",
				"seat_management_setting": "assign_selected",
				"total_seats": 5
			},
			"copilot_evaluation": {
				"recommendations": [
					{
						"category": "copilot_cost",
						"issue": "Copilot seat utilization: 5 active, 0 inactive out of 5 total",
						"learn_more": "https://docs.github.com/en/copilot/managing-copilot/managing-github-copilot-in-your-organization/reviewing-activity-related-to-github-copilot-in-your-organization/reviewing-your-organization-s-copilot-seat-assignments",
						"recommendation": "Monitor seat utilization regularly for cost efficiency",
						"severity": "info"
					}
				],
				"summary": {
					"high_severity": 0,
					"info": 1,
					"low_severity": 0,
					"medium_severity": 0,
					"total_issues": 1
				}
			},
      ...

It's nice that it also looks at running costs. Seat management takes surprisingly more effort than you'd think.

Structure of the Markdown report

Markdown is useful when you want to review the scan results as text.
Pasting the results of a per-repository scan into an issue is also an option.

Here is an excerpt of the beginning.

# GitHub Assessment Report — your-org

**Scope:** Organization
**Generated:** April 30, 2026
**Scan Coverage:** 0 enterprises / 1 organizations / 4 repositories

---

## Executive Summary

> The overall security and best practices posture of this environment **requires immediate attention**. A total of **33 findings** were identified across 0 enterprises, 1 organizations, and 4 repositories. Of these, **4 are critical** and **3 are high severity**, requiring prompt remediation. An additional **11 medium-severity** findings should be addressed within 60 days. The most prevalent area of concern is **Community Health & Documentation** with 8 findings. The top improvement opportunity is to enable branch protection and Dependabot alerts across all repositories.

### Posture Scorecard

| Entity | Type | Critical | High | Medium | Low | Info |
|--------|------|----------|------|--------|-----|------|
| your-org | org | 0 | 1 | 3 | 0 | 0 |
| your-org/xx1 | repo | 1 | 1 | 2 | 4 | 0 |
| your-org/xx2 | repo | 1 | 0 | 2 | 3 | 0 |
| your-org/xx3 | repo | 1 | 0 | 2 | 4 | 0 |
| your-org/xx4 | repo | 1 | 1 | 2 | 4 | 0 |

### Overall Risk Distribution

| Severity | Count | % of Total |
|----------|-------|------------|
| 🔴 Critical | 4 | 12% |
| 🟠 High | 3 | 9% |
| 🟡 Medium | 11 | 33% |
| 🟢 Low | 15 | 45% |
| ℹ️ Info | 0 | 0% |
...

Structure of the Excel report

The Excel file is useful when you want an overview of the report.

For example, if you want to filter a large number of repositories to those with many Critical items or Critical Findings, Excel is the natural way to do it.

The Excel file is divided into the following sheets.

  • Organizations
  • Repositories
  • Branch Protection
  • Findings

Here is an excerpt of the beginning of the Repositories sheet.

ghqr-security

ghqr mcp : Start as an MCP server and investigate exploratively from Claude Code

ghqr also has an MCP server mode.

When started with --mode http, it exposes two endpoints by default: /sse (event stream) and /message (POST).

export GH_TOKEN=github_pat_xxxxxxxxxxxx
ghqr mcp --mode http --addr :8080
# Starting MCP server in HTTP/SSE mode on :8080

With Claude, add the MCP server as follows.

claude mcp add ghqr --transport sse http://localhost:8080/sse

You can also edit the MCP configuration file directly.

{
  "mcpServers": {
    "ghqr": {
      "type": "sse",
      "url": "http://localhost:8080/sse",
      "headers": {},
      "tools": ["*"]
    }
  }
}

Let's call it from Claude Code.

> ghqr でgithub org(your-org) を scan して
...

⏺ スキャン完了しました。

  ghqr スキャン結果: your-org

  成果物
  - /Users/jsmith/ghqr/ghqr_20260430_204115.json

  (MCP 経由のスキャンでは JSON のみ生成。.md/.xlsx は CLI 直叩き時のみ出力される模様)

  Org レベル所見

  セキュリティ
  - 2FA 必須化 OFF (org-sec-001 high)
  - Web commit signoff 未設定 (org-sec-002 medium)
  - メンバーが Public リポジトリを作成可能 (org-sec-004 medium)
  - Security Manager チーム未割当 (org-sec-005 medium)
...
  横断的な傾向
  - 全リポジトリで default branch の Branch Protection 未設定 (critical)
  - CODEOWNERS / SECURITY.md がいずれも未配置
  - description / topics 未設定が多くガバナンス上の見通しが悪い

  詳細は JSON の evaluation.recommendations を参照してください。

> critial と high がある xx1 はどうすれば良い?

⏺ xx1 の問題を整理すると最終 push が 2025-02-04 で約 15 ヶ月放置 (repo-meta-003 dormant も同時検出)。「使うか / 使わないか」で対応が分岐します。

  判断フロー

  A. もう使わない場合 (推奨候補)

  archive すれば read-only になり、Branch Protection も Dependabot も無関係になります。critical/high が一発で消えます。
...

Let's archive the problematic repository and rescan it.

> リポジトリ xx1 をもう一回スキャンして 

⏺ your-org/xx1 の再スキャン結果です。

  成果物
  - /Users/jsmith/ghqr/ghqr_20260430_204532.json

  変化点

  リポジトリは archived = true に変更済み (前回 false)。

  残った Recommendation

  ┌──────────┬────────────────┬───────────────────────────────────┐
  │ severity │    rule_id     │               issue               │
  ├──────────┼────────────────┼───────────────────────────────────┤
  │ high     │ repo-sec-001   │ Dependabot alerts not enabled     │
  ├──────────┼────────────────┼───────────────────────────────────┤
  │ info     │ (rule_id なし) │ Repository is archived (情報通知) │
  ├──────────┼────────────────┼───────────────────────────────────┤
  │ medium   │ repo-meta-001  │ Repository has no description     │
  └──────────┴────────────────┴───────────────────────────────────┘

  解釈

  archive 化で前回検出されていた critical の repo-bp-001 (Branch Protection) は消えました。archive により書き込みが拒否されるため、保護ルールが事実上不要になったという判定です。

  ただし repo-sec-001 (Dependabot alerts) と repo-meta-001 (description) は archived とは無関係に残ります。

  実害観点
  - archived = read-only 状態なので Dependabot を有効化しても新しい依存追加はもう発生せず、既存依存のアラート受信のみ意味を持つ。脆弱性監視を継続したい場合のみ ON にすべき。完全に塩漬け運用なら無視で問題なし。
  - description は archive 後も付けられます。一覧での見通しのため gh repo edit your-org/xx1 --description "..." で追加可。

  要約: ghqr の警告は実質「info ノイズ」レベルで、archive により実害のあるリスクは消えています。

When investigating exploratively, the MCP interface is handy.

In closing

I introduced how to check GitHub settings against best practices in bulk using ghqr, Microsoft's official OSS.

  • Can inspect at the Enterprise/Organization/Repository level
  • Generates xlsx / Markdown / JSON reports with a single CLI command
  • Presents even remediation actions on a per-control basis

GitHub operations tend to become dependent on specific individuals, and ongoing security work tends to be neglected, but running ghqr regularly is expected to lower the barrier to taking stock of settings and fixing them.

For that kind of future, I'd like to see the check items expand (since it's OSS, you can send as many PRs as you like).

References

Share this article