Domain 5: Enable Secure Software Development and Ensure Compliance (36%) โ
โ Domain 4 ยท Next Domain โ
Domain 5 = 36% of the Exam
This is the highest-weighted domain. Master every section here before moving to others. Expect questions covering secret scanning, CodeQL, Dependabot, audit logs, token types, GitHub Apps, OAuth Apps, and Enterprise Managed Users.
GitHub's Security Posture for the Enterprise โ
GitHub provides a layered security model. Admins are responsible for enabling, configuring, and enforcing these layers.
Security Policy in a Repository โ
- A security policy (
SECURITY.md) tells users how to responsibly disclose vulnerabilities in a project. - Located in the repo root,
.github/, or the org's default community health files. - GitHub surfaces the security policy on the repo's Security tab.
Dependency Security โ
The Dependency Graph โ
- GitHub automatically parses package manifests (e.g.,
package.json,Gemfile,pom.xml) to build a dependency graph. - Shows all direct and transitive dependencies for a repository.
- Powers Dependabot alerts โ must be enabled for Dependabot to function.
Dependabot โ
Dependabot monitors your dependency graph for known vulnerabilities and helps you fix them.
| Feature | What it does |
|---|---|
| Dependabot Alerts | Notifies you when a dependency has a known CVE (via the GitHub Advisory Database) |
| Dependabot Security Updates | Automatically opens a PR to update the vulnerable dependency to a safe version |
| Dependabot Version Updates | Keeps dependencies up to date regardless of CVEs (optional, scheduled) |
Enabling Dependabot โ
- Enable the Dependency graph (org or repo level)
- Enable Dependabot alerts (org settings or repo security settings)
- Optionally enable Dependabot security updates (auto-PRs)
Exam Tip
Dependabot alerts notify you. Dependabot security updates actually open a fix PR. Know the difference โ many questions ask about which one to enable for a specific outcome.
Vulnerable Dependency Response Plan โ
- Detect: Dependabot alert fires for a CVE in a dependency
- Assess: Review the alert โ is the vulnerable code path actually used?
- Remediate: Merge the Dependabot security update PR or pin to a safe version
- Verify: CI passes, no regressions
- Monitor: Keep Dependabot enabled for future alerts
Code Scanning and CodeQL โ
Code Scanning โ
Code scanning analyzes source code for vulnerabilities and coding errors before they reach production.
- Implemented via GitHub Actions (or third-party SARIF tools)
- Results appear in the Security tab โ Code scanning alerts
- Alerts include the vulnerable line, severity, and remediation guidance
CodeQL โ
CodeQL is GitHub's static analysis engine for code scanning.
- Treats code as data โ writes queries to find patterns that represent vulnerabilities (e.g., SQL injection, XSS, path traversal)
- Maintained by GitHub; updated regularly with new vulnerability patterns
- Supports: C, C++, C#, Go, Java, JavaScript, Python, Ruby, Swift
Setting Up CodeQL โ
# .github/workflows/codeql.yml
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript, python
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3- Run on
push,pull_request, and/or a scheduledcron - Results are uploaded to the Security tab automatically
Trap
Code scanning (CodeQL) analyzes source code. Secret scanning scans for credentials and tokens. They are different tools solving different problems.
Secret Scanning โ
Secret scanning detects credentials, API keys, and tokens that have been committed to a repository.
How It Works โ
- GitHub maintains a database of known secret patterns (AWS keys, GitHub tokens, Stripe keys, etc.)
- Scans all commits pushed to the repo
- Alerts are shown in the Security tab โ Secret scanning alerts
- For partner patterns (e.g., AWS, Stripe): GitHub automatically notifies the secret issuer, who can revoke the token
Push Protection โ
- Push protection blocks a push if it contains a detected secret, before it lands in the repo
- Users can bypass push protection with a justification, which is logged
- Enabled in: Organization Settings โ Code security and analysis โ Push protection
Critical
Push protection prevents secrets from ever entering the repo. Secret scanning alerts notify you after a secret is already committed. Enable both for maximum protection.
Scrubbing Sensitive Data from Git History โ
If a secret is already in the repo's commit history, it must be removed:
BFG Repo Cleaner (Recommended) โ
- Fast, purpose-built tool for removing large files or sensitive strings from Git history
- Simpler syntax than
filter-branch - Command:
bfg --replace-text passwords.txt my-repo.git - After BFG: force-push cleaned history, all collaborators must re-clone
git filter-branch (Legacy) โ
- Built into Git โ no additional tool needed
- Slower on large repos; complex syntax
- Still valid and accepted by GitHub Support, but BFG is preferred
Scrubbing via GitHub Support โ
If a secret was pushed to a public repo and indexed by search engines or cached, removing it from history is not enough. Steps:
- Revoke/rotate the secret immediately
- Remove it from history (BFG)
- Contact GitHub Support to purge cached views and force-crawlers to update
Trap
Removing a secret from Git history does not mean it's safe โ it may have been cached, logged, or used. Always revoke the credential first, then clean the history.
Audit Log APIs โ
The audit log records all significant actions taken within an org or enterprise โ who did what, when, and from where.
Use Cases โ
- Compliance reporting (SOC 2, ISO 27001)
- Forensic investigation (who deleted a repo, who changed branch protections)
- Streaming events to a SIEM (Splunk, Datadog, Elastic)
REST API โ
GET /orgs/{org}/audit-log
GET /enterprises/{enterprise}/audit-log- Filter by action type:
?phrase=action:repo.delete - Filter by user:
?phrase=actor:username - Paginated results, supports streaming
GraphQL API โ
{
organization(login: "my-org") {
auditLog(first: 100) {
edges {
node {
... on RepoDeleteAuditEntry {
action
actor { login }
createdAt
repositoryName
}
}
}
}
}
}Exam Tip
Use REST for simple filtered queries and streaming. Use GraphQL when you need to shape the response or join multiple entity types in one request.
Access Tokens โ
GitHub supports multiple token types. The exam tests your knowledge of when and why to use each.
Token Types โ
| Token | Scope | Expiration | Best For |
|---|---|---|---|
| Personal Access Token (PAT) | User-scoped | Optional (classic PATs don't expire; fine-grained PATs do) | Personal automation, CLI access |
| Fine-grained PAT | Specific repo and permission scope | Required (max 1 year) | Scoped personal access with expiry |
| GitHub App Installation Token | App-scoped permissions | 1 hour | Machine accounts, CI/CD integrations |
| OAuth Token | User-delegated (OAuth flow) | Until revoked | Apps acting on behalf of users |
| Device Token | OAuth device flow | Until revoked | CLI/headless OAuth |
| Refresh Token | Renews OAuth tokens | Longer-lived | Maintaining OAuth sessions |
Rate Limits by Token Type โ
- PAT / OAuth Token: 5,000 requests/hour per user
- GitHub App Installation Token: 5,000 requests/hour per installation + 15,000 requests/hour at enterprise level
- Unauthenticated: 60 requests/hour
GitHub Apps vs OAuth Apps โ
GitHub Apps (Preferred) โ
- Installed on an org or repo (not tied to a specific user)
- Uses installation tokens โ short-lived (1 hour), scoped to specific permissions
- Can subscribe to webhooks and respond to events
- Granular permissions: repository permissions, org permissions, account permissions
- If the installing user leaves, the app keeps working
OAuth Apps โ
- Acts on behalf of a user (uses the user's identity)
- Broader permission scopes (less granular)
- If the user's account is suspended or deleted, the app loses access
- Better for user-facing integrations (social login, user dashboards)
GitHub App vs OAuth App Comparison โ
| GitHub App | OAuth App | |
|---|---|---|
| Identity | App identity (installation) | User identity |
| Token | Installation token (1 hr) | OAuth token (longer-lived) |
| Permission scope | Fine-grained (repo, org, account) | Broader (read/write on user resources) |
| Webhook support | Built-in | No |
| Best for | CI/CD bots, integrations, automation | User-facing apps, social login |
| Resilience | Survives user leaving | Breaks if user is removed |
Trap
For machine accounts and bots, always recommend GitHub Apps over OAuth Apps or PATs. GitHub Apps are more secure, more auditable, and don't break when a specific user's account is modified.
Approving and Denying Apps โ
Enterprise admins can control which GitHub Apps and OAuth Apps are allowed in the org:
- Organization Settings โ GitHub Apps โ Allowed apps
- Organization Settings โ OAuth app access policy
- Can restrict to: admin-approved apps only, or allow all
Machine Accounts vs GitHub Apps โ
| Machine Account (Bot User) | GitHub App | |
|---|---|---|
| What it is | A real GitHub user account used for automation | A proper API integration (not a user) |
| License seat | Consumes a seat | Does not consume a seat |
| Token type | PAT | Installation token |
| Auditability | Appears as user in audit logs | Appears as app in audit logs |
| Preference | Legacy approach | Preferred by GitHub |
Enterprise Managed Users (EMU) โ
EMU is a GitHub Enterprise feature where user accounts are fully managed by the enterprise.
Key Characteristics โ
- Users cannot create or use personal GitHub.com accounts โ all identities are provisioned by the enterprise via SCIM
- EMU accounts can only access resources within the enterprise (no public repos, no external forks)
- Usernames are controlled by the enterprise IdP
- Requires GHEC or GHAE (not supported on GHES)
When to Use EMU โ
- Organization requires full control over user identities
- Users must not have any access to public GitHub repos
- Compliance requires all access to be company-managed
Exam Tip
EMU is the most restrictive identity model. If a question mentions "users should not have personal GitHub accounts" or "all access must be company-managed," the answer is Enterprise Managed Users.
SSH Keys and Deploy Keys โ
SSH Keys โ
- Users add SSH keys to their GitHub account for Git authentication (
git clone git@github.com:...) - Scoped to the user's account โ gives the same access the user has
Deploy Keys โ
- SSH keys added directly to a specific repository (not a user account)
- Used by CI/CD systems, servers, or scripts that need access to one repo
- Can be read-only or read-write
- More secure than a PAT or user SSH key because they're repo-scoped
Exam Tip
Use a Deploy Key (read-only) when a server or script needs to clone a single private repo. Use a GitHub App when the automation needs to interact with multiple repos or APIs.
Domain 5 Quick Quiz
What is the difference between secret scanning and push protection?
(Click to reveal)