Gitfence

CODEOWNERS Is Not Access Control (What It Actually Does)

GitHub CODEOWNERS requests reviews and can require approvals, but it doesn't stop anyone reading or cloning code. What it does, what it doesn't, and fixes.

Gitfence team6 min read

Short answer: CODEOWNERS controls who is asked to review changes to a path, and with branch protection, whose approval is required to merge them. It doesn't restrict who can read, clone or even push to that path on other branches. If someone can read the repository, they can read every file listed in CODEOWNERS. To hide code you need a separate repository or a filtered view.

What CODEOWNERS does

A CODEOWNERS file maps path patterns to people or teams. GitHub's documentation describes the core behavior in one sentence: "Code owners are automatically requested for review when someone opens a pull request that modifies code that they own."

# .github/CODEOWNERS
*                   @acme/eng-leads
/core/              @acme/core
/core/pricing/      @alice @acme/pricing
/infra/             @acme/platform
*.sql               @acme/data
/.github/           @acme/platform

Facts from the docs worth knowing:

  • Location. GitHub looks in .github/, the repository root, then docs/, and uses the first CODEOWNERS it finds.
  • Base branch. "For code owners to receive review requests, the CODEOWNERS file must be on the base branch of the pull request," so different branches can have different owners.
  • Last match wins. Later patterns override earlier ones, so put general rules first.
  • Syntax. Mostly gitignore-style patterns, with exceptions: "Using ! to negate a pattern doesn't work."
  • Errors are visible. Open the CODEOWNERS file on GitHub to see errors highlighted; a user or team "that doesn't exist or has insufficient access" isn't assigned.
  • Owners need write access. "The people you choose as code owners must have write permissions for the repository. When the code owner is a team, that team must be visible and it must have write permissions."
  • Size limit. Files over 3 MB aren't loaded.

Making it mandatory

On its own, CODEOWNERS only requests reviews. To make owner approval a requirement, enable Require review from Code Owners in a branch protection rule or ruleset for the target branch. Then a pull request touching /core/pricing/ can't merge into main until an owner approves. Per GitHub, "an approval from any of the owners is sufficient."

What CODEOWNERS does not do

Common assumption Reality
Non-owners can't see /core/ Anyone with Read access can clone the whole repository
Non-owners can't change /core/ They can commit and push to their own branches; only merging into protected branches needs approval
Owners are the only people who can approve Any reviewer can approve; the rule requires at least one owner approval
It applies everywhere Only to branches with a rule requiring code owner review
It restricts AI agents Agents with repository access read everything like anyone else
It protects secrets A secret in /infra/ is readable by every collaborator

It's a review routing and merge-approval tool. That's useful, but it's about integrity (what gets merged), not confidentiality (who can see).

Branch protection and rulesets set merge requirements per branch: required reviews, status checks, signed commits, linear history, who can push.

Push rulesets add path rules. "Restrict file paths" will "prevent commits that include changes in specified file paths from being pushed to the repository", for private and internal repositories and their fork networks. That's closer to path-level write control than CODEOWNERS, but it's still write-only.

Repository roles (Read, Triage, Write, Maintain, Admin) control what someone can do with the entire repository. There's no path-level read role on any plan.

Putting it together:

Goal Tool
Route reviews to the right team CODEOWNERS
Require an owner's approval to merge CODEOWNERS + "Require review from Code Owners"
Block pushes touching a path Push ruleset: restrict file paths
Stop someone from reading a path Not available on GitHub; separate repo or filtered view

Common CODEOWNERS mistakes

  1. Unprotected CODEOWNERS file. If anyone can change CODEOWNERS in a PR, they can add themselves. Own /.github/ (or wherever the file lives) with a trusted team, and require code owner review on the default branch.
  2. Owners without write access. Individuals or teams lacking write permission are not requested for review. Check the CODEOWNERS errors shown on the file in GitHub.
  3. Order mistakes. A catch-all * at the bottom overrides everything above it.
  4. Assuming it hides code from contractors. This is the big one. If you added a contractor to the repository because "CODEOWNERS will protect /core/", they can read /core/.

If you need to restrict reading

The options are covered in depth in can you restrict access to folders in a GitHub repository?. In brief:

  • Split the code into its own repository, so GitHub's repository permissions apply.
  • Submodule the sensitive part, so people without access get an empty folder.
  • Publish a filtered mirror with Copybara or git filter-repo.
  • Serve filtered views with a proxy.

Not options: sparse checkout (why), .gitignore, or editor ignore files.

How Gitfence complements CODEOWNERS

Gitfence handles the part CODEOWNERS can't: who can see what. It sits in front of GitHub and gives each restricted person or AI agent a clone that contains only what they're allowed to see, with per-folder or per-file levels: No access, Types only, Can read, Can edit.

Their pushes are checked path by path and arrive in GitHub as ordinary pull requests, so your CODEOWNERS file, branch protection and rulesets apply to them exactly as before. The two work together:

  • CODEOWNERS and branch protection decide who approves what gets merged.
  • Gitfence decides who can see and change which paths in the first place, before a PR exists.

Gitfence also adds a Gitfence check to each PR from a restricted person. It identifies the human and agent behind the change and scans added lines for fingerprints of hidden code, failing without quoting the hidden source. That helps catch hidden code copied into a visible file. It's a deterrent, not proof: transformed or encoded code can evade fingerprinting.

A practical way to start: the paths your CODEOWNERS file assigns to a core team are usually the same paths contractors and agents don't need to see.

For teams sharing a monorepo, the two combine as described in monorepo permissions for per-team access, and for AI agents in least-privilege repo access for Claude Code, Codex and Cursor.

Today Gitfence works with GitHub only. See how it works and Gitfence for contractors.

FAQ

Can CODEOWNERS prevent someone from viewing files?

No. It only affects review requests and, with branch protection, merge approvals. Anyone with read access to the repository can view every file.

Can someone push changes to code they don't own?

Yes, to branches without protection. CODEOWNERS approval is enforced when merging into branches with "Require review from Code Owners" enabled. Push rulesets can block pushes that touch specific paths.

Why is my code owner not being requested for review?

Most often the user or team lacks write permission, the team isn't visible, or a later pattern in the file overrides the one you expected. GitHub shows errors on the CODEOWNERS file when it can't resolve an owner.

Can a code owner have read-only access?

No. GitHub requires code owners to have write permission. This is a long-standing community request.

Does CODEOWNERS work on GitHub Free?

Code owners can be used on public repositories with GitHub Free, and on private repositories with paid plans. Requiring code owner review uses branch protection or rulesets, whose availability for private repositories also depends on your plan; check GitHub's current plan documentation.

Fence your first repository in minutes

Free for one repository and your own team. Add a restricted person and Pro is free for 14 days, no card.