GitHub Advanced Security configuration enforcement now has an enterprise-level control for who may override enforced settings. An enterprise administrator can keep the previous repository-only boundary or extend enforcement so organization owners cannot change the protected settings either. That distinction matters when an enterprise has delegated organization administration but still needs one security baseline.
The safe rollout is not simply “turn on enforcement.” Decide which settings the configuration truly owns, check license coverage and repository prerequisites, apply the strict scope to a canary organization, and collect readback from the enterprise configuration and its repositories. This guide builds that evidence without treating an accepted API request as proof that enforcement worked.
Table of Contents
How GitHub Advanced Security configuration enforcement changes authority
GitHub announced the expanded control on September 15, 2026. An enterprise security configuration now exposes three enforcement choices:
- Don’t enforce: the configuration can be attached, but its settings are not protected from overrides.
- Enforce for repository owners: repository administrators cannot change settings owned by the configuration, while organization owners retain authority.
- Enforce for repository and organization owners: both repository and organization administrators are prevented from overriding the enforced settings.
The third option is the important change for centrally governed enterprises. It moves the final security-policy boundary above the organization. Enterprise administrators remain responsible for the configuration, while delegated administrators can continue managing repositories and organization-level operations that are outside that enforced policy.
Enforcement does not freeze every security setting. GitHub’s documentation states that only features explicitly configured as enabled or disabled are enforced. A feature left as Not set stays outside the configuration’s control and may still differ by repository. Treat the configuration as an allowlist of governed settings, not as a blanket lock.
Choose what the configuration must own
Start with the authority decision, not the dropdown. For each feature, name the risk owner and decide whether a repository or organization exception is legitimate. A configuration that governs too little leaves gaps; one that governs every available switch can block teams that have different languages, runners, or secret-scanning requirements.
| Setting | Typical enterprise decision | Exception to plan for |
|---|---|---|
| Secret scanning | Enable and enforce for covered repositories | License eligibility and repository visibility |
| Push protection | Enable and enforce when bypass governance is defined | Delegated bypass reviewers and emergency workflow |
| Code scanning default setup | Enable only after language and runner preflight | Unsupported languages, unavailable Actions, or custom advanced setup |
| Dependabot alerts | Enable broadly | Repository prerequisites and alert ownership |
| Features without a central mandate | Leave Not set | Document who owns the repository-level choice |
Record this matrix before changing enforcement. It becomes the review boundary: security can prove which settings are centrally owned, and organization administrators can see which choices remain delegated. It also prevents a later edit from quietly expanding the policy beyond its approved scope.
Run a production preflight
Before enabling the stricter scope, inventory the repositories that will receive the configuration and confirm that the required paid features are licensed. GitHub warns that when an enterprise configuration is attached without enough GitHub Advanced Security licenses, only free features are enabled. A successful attachment therefore does not guarantee full protection.
- Export the configuration’s current feature values and enforcement state.
- Count private and internal repositories that require licensed Code Security or Secret Protection features.
- Identify repositories that use advanced code scanning setup, custom runners, or unsupported languages.
- Confirm that GitHub Actions and any required actions are available to repositories using default setup.
- List existing organization or repository exceptions and assign an owner to each one.
- Choose a small canary organization with representative repositories and an available rollback window.
Code scanning deserves special attention. GitHub documents conditions that can break enforcement, including disabling GitHub Actions after default setup depended on it, making required actions unavailable, or changing the languages excluded from default setup. Resolve those conflicts before the enterprise setting removes the local override path.
Defaults and enforcement solve different problems. A default configuration applies automatically to matching new repositories, but transferred repositories may still need explicit handling. Enforcement controls whether attached settings can be overridden. Verify both attachment coverage and the selected enforcement scope.
Stage enforcement with a canary organization
Open the enterprise’s code security configuration in GitHub, select Enforce for repository and organization owners, and apply it first to the approved canary scope. Capture the configuration ID, the selected enforcement option, the feature values, the change ticket, and the exact time. The UI choice is the authoritative evidence for the new scope; the REST representation may not expose that scope as a separate new enum.
Keep the canary long enough to observe configuration attachment and feature activation. Repositories can pass through transitional states such as attaching or updating. Do not promote while any repository is failed, while expected licensed features remain absent, or while code scanning has lost its required Actions path.
- Security owner: approves the governed feature matrix and final scope.
- Enterprise administrator: changes the enforcement control and preserves UI evidence.
- Organization owner: confirms that delegated workflows still operate and attempts no unauthorized bypass.
- Repository owner: validates code scanning, secret scanning, and Dependabot behavior on representative repositories.
Separate these checks from feature rollout when possible. Changing the configuration’s contents, attachment coverage, and authority boundary at the same time makes a failure difficult to diagnose and a rollback harder to scope.
Verify configuration and repository coverage
Use read-only REST calls to preserve evidence after the UI change. Enterprise configuration endpoints require an enterprise administrator. GitHub’s REST documentation currently says these enterprise endpoints work with OAuth or classic personal access tokens that have the required enterprise scope, but not with GitHub App tokens or fine-grained personal access tokens.
#!/usr/bin/env bash
set -euo pipefail
: "${ENTERPRISE:?Set the enterprise slug}"
: "${CONFIG_NAME:?Set the exact configuration name}"
api_version="2026-03-10"
snapshot="artifacts/ghas-enforcement"
mkdir -p "$snapshot"
gh api --paginate \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: $api_version" \
"/enterprises/$ENTERPRISE/code-security/configurations?per_page=100" \
| jq -s 'add' > "$snapshot/configurations.json"
matches="$(jq --arg name "$CONFIG_NAME" \
'[.[] | select(.name == $name)] | length' \
"$snapshot/configurations.json")"
test "$matches" -eq 1
config_id="$(jq -r --arg name "$CONFIG_NAME" \
'.[] | select(.name == $name) | .id' \
"$snapshot/configurations.json")"
gh api --paginate \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: $api_version" \
"/enterprises/$ENTERPRISE/code-security/configurations/$config_id/repositories?per_page=100&status=all" \
| jq -s 'add' > "$snapshot/repositories.json"
jq -r '.[] | [.name, .status] | @tsv' \
"$snapshot/repositories.json" | sort
jq -e '[.[] | select(.status == "failed")] | length == 0' \
"$snapshot/repositories.json"
The script fails closed when the configuration name is missing or ambiguous, then captures every associated repository and rejects a failed attachment. The endpoint is cursor-paginated, so --paginate is essential for an enterprise with more than one page of configurations or repositories. Keep the raw JSON as audit evidence instead of saving only the filtered table.
Repository-level readback adds a second view. For a representative repository, call GET /repos/{owner}/{repo}/code-security-configuration and verify the returned configuration ID, name, feature values, and attachment status. That endpoint supports fine-grained tokens with repository Administration read permission, unlike the enterprise-level listing.
owner="example-org"
repo="payments-api"
gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" \
"/repos/$owner/$repo/code-security-configuration" \
| tee "artifacts/ghas-enforcement/$owner-$repo.json" \
| jq '{status, configuration: {
id: .configuration.id,
name: .configuration.name,
enforcement: .configuration.enforcement,
code_scanning_default_setup: .configuration.code_scanning_default_setup,
secret_scanning: .configuration.secret_scanning,
secret_scanning_push_protection: .configuration.secret_scanning_push_protection
}}'
This readback shows which configuration manages the repository and which feature values arrived. It does not replace the captured enterprise UI evidence for whether organization owners are also blocked. Preserve both pieces because they prove different parts of the rollout.
Do not trust a successful mutation alone
GitHub documents an important enforcement behavior: a REST request that tries to change the enablement of a feature controlled by an enforced configuration can appear to succeed without changing the setting. An HTTP success response is therefore transport evidence, not policy-state evidence.
Every automation that writes a governed setting should perform an independent read-after-write and compare the observed value with the requested value. If they differ, report the configuration that owns the setting and stop retrying. Blind retries add noise and can hide that the request was blocked by policy rather than by a transient API failure.
- Log the request target, requested value, response status, and request ID.
- Read the repository’s attached configuration and effective feature value.
- Classify an unchanged governed value as
BLOCKED_BY_ENFORCED_CONFIGURATION, not as success. - Send the exception to the enterprise security owner instead of asking an organization owner to bypass the policy.
The same principle applies to asynchronous attachment. A 202 Accepted response means GitHub accepted the work; it does not prove that every repository reached attached or enforced. Poll the read-only status endpoint with a bounded timeout and preserve the final state.
Handle failures and rollback
Stop the rollout when a canary repository reports failed, a paid feature is missing, code scanning loses its execution path, or the configuration owns a setting that the approved policy meant to delegate. Do not expand to more organizations while the evidence is incomplete.
- Insufficient licenses: narrow the eligible repository set or obtain coverage; do not describe free-feature attachment as full GHAS protection.
- Code scanning failure: restore GitHub Actions and required actions, correct the language exclusions, or leave default setup outside the enforced configuration until the prerequisite is ready.
- Wrong ownership boundary: change the scope back to repository owners only while the enterprise reviews organization-level exceptions.
- Wrong feature matrix: restore the exported configuration values, then re-run repository readback before promotion.
- Transferred or newly discovered repository: attach the approved configuration explicitly and verify its status rather than assuming the default covered it.
A rollback should reverse one layer at a time. First restore the previous enforcement scope if delegated administration is blocked unexpectedly. Then restore configuration contents only if the feature values themselves are wrong. Keep the failed snapshot, the restored snapshot, and the repository status diff so the next attempt starts from evidence rather than memory.
The stronger GitHub Advanced Security configuration enforcement option is useful because it makes enterprise ownership explicit. Its production value depends on a narrow governed-feature matrix, representative canaries, license and Actions preflight, and readback at both enterprise and repository levels. When those controls are present, organization-level administration can remain delegated without turning the enterprise security baseline into a suggestion.
References
- GitHub Changelog: Enforce GitHub Advanced Security configurations
- GitHub Docs: Create a custom security configuration
- GitHub Docs: Configuration enforcement
- GitHub REST API: Code security configurations
Found this useful? Support more practical developer content.