Consistent coverage across an enterprise after a merger
The enterprise has 300 repositories: 180 public open-source projects and 120 private business applications. Security tooling grew ad hoc: 22 private repositories have code scanning, 9 have secret scanning, and 4 have push protection. The CISO wants consistent coverage on every private repository and has budget approval for 55 GitHub Advanced Security committers. Of the 120 private repositories, 30 are archived, 15 are forks of public upstream projects kept for patch review, 12 contain only documentation and Terraform, and the rest are active; the 8 most active repositories have a large shared pool of committers. A merger added two organizations with their own admins, and repository admins habitually disable scanning when builds slow down. One team writes Elixir and asks what coverage they can get.
1. How do you determine whether 55 licenses covers the estate, and what do you enable where?
Read the worked answer
Count active committers, not repositories. GitHub Advanced Security for private repositories is billed per unique active committer (someone who pushed in the last 90 days) to repositories where GHAS is enabled; public repositories are free. So 55 may or may not be enough, depending on deduplication across repositories and organizations - measure unique committers, never sum per-repo contributor counts.
Then decide what to enable where. Archived repositories and public-upstream forks usually have few or no active committers, so they cost little but generate alert noise; documentation and Terraform repositories still benefit from secret scanning and push protection, because infrastructure credentials are exactly what leak there. Prioritize code scanning for repositories containing deployable code, and do not let the license number push you into skipping secret scanning on high-risk infrastructure repositories. Model the actual cost on the billing page after enabling, before committing to all 120.
2. How do you enforce consistent configuration while accommodating unsupported languages?
Read the worked answer
Use enterprise-level code security configurations so coverage is defined once rather than by repository admins. Create configurations by risk tier - for example, business-critical with code scanning default setup, secret scanning, push protection, and dependency review; infrastructure with secret scanning, push protection, and Dependabot; public with the free defaults - and attach repositories using custom properties instead of naming them individually. Set configurations to enforced at the enterprise so organization owners and repository admins cannot override them, and define the default configuration for newly created repositories.
For Elixir, CodeQL has no support. Combine secret scanning, push protection, Dependabot, dependency review, and a third-party SAST tool that uploads SARIF with a distinct category. Record the coverage gap as a risk exception with an owner and review date, and let Security Overview show it honestly rather than letting the repository appear fully covered.
3. What controls stop admins from quietly disabling scanning after the merger?
Read the worked answer
Enforcement plus detection. Enterprise-level configuration enforcement is the only reliable control after an acquisition, because it applies regardless of which organization owns the repository and cannot be overridden by repository admins. Apply enforced configurations to both acquired organizations and verify in the coverage view that every repository reports the expected configuration.
Add accountability: stream the audit log to a SIEM and alert on events that change security configurations, disable secret scanning, or remove push protection, and on large numbers of alert dismissals by one actor. Grant configuration authority to security managers rather than every admin.
For build slowdowns, the answer is performance tuning - path filters, scheduled rather than per-push analysis, splitting large repositories - not disabling scanning. Publish an exception process with a named approver, an expiry date, and recorded justification so temporary disabling is visible and reversible.