I Tried Diagnosing GitHub Settings Against Best Practices with Microsoft's Official OSS "ghqr"
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.
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.
Installation
Install from assets
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.
ghqr list-recommendationsOutputs the list of recommendationsghqr scanRuns a scanghqr mcpStarts 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_TOKENis 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 toghqr scan -e my-ent: Under a specific Enterpriseghqr scan -o my-org: Under a specific Organizationghqr 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 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).