Audit Logs, Security Policies, Compliance Evidence, Repository Governance, and Enterprise Controls: Diagnostics, Failure Modes, Security, and Performance
Diagnose missing or misleading audit evidence, unenforced policy, weak exceptions, retention gaps, and control drift without treating absence of a log event as proof.
Learning objectives
- Apply an evidence-first diagnostic sequence to governance failures.
- Repair filters/time windows before concluding that events are absent.
- Recognize platform-only retention and unenforced Markdown policy as control weaknesses.
- Diagnose unowned/unexpired exceptions and enterprise policy overrides.
- Treat destructive or privilege-changing operations as controlled incident actions.
1. Diagnostic sequence: preserve → scope → inspect → correct → verify
Governance troubleshooting is dangerous when the first response changes the system you are trying to understand. Preserve raw events, relevant Git refs, rule/configuration JSON, permissions, and timestamps before mutation. Then identify the exact organization, repository, actor, ref, workflow, policy, and time range. Inspect authorization and product boundaries. Choose the least destructive correction. Finally, independently verify both current state and evidence collection.
1. Preserve raw evidence and hashes.
2. Identify repository / organization / enterprise / actor / resource / time scope.
3. Inspect current settings, permissions, rules, Git refs, logs, and API responses.
4. Check plan/deployment and retention/event-coverage boundaries.
5. Apply the smallest correction that restores the intended control.
6. Re-query/re-inspect and retain before/after evidence.
7. Record owner, rationale, incident/change ID, and any exception expiry.
2. Intentionally broken example: the wrong event family returns an empty result
Suppose an Enterprise Cloud organization owner knows a repository ruleset was created but this command prints nothing:
ORG="octo-c29-lab"
gh api --method GET --paginate -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2026-03-10" -f phrase='created:>=2026-08-19 action:repository_ruleset.create' -f include='git' -f per_page=100 "orgs/$ORG/audit-log" --jq '.[]'
The HTTP call may succeed with 200 OK and an empty
array. The bug is conceptual:
repository_ruleset.create is a web/audit event, but the
query asked for Git events only. A successful HTTP status means the
API accepted the request; it does not mean the query represented
your investigative intent.
Repair the event family first, then keep the time range narrow:
gh api --method GET --paginate -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2026-03-10" -f phrase='created:>=2026-08-19 action:repository_ruleset.create' -f include='web' -f per_page=100 "orgs/$ORG/audit-log" --jq '.[] | {timestamp:."@timestamp",action,actor,repo,ruleset_name,ruleset_enforcement}'
If the corrected query is still empty, investigate retention, permission, exact organization/repository, action coverage, and whether the expected mutation actually completed.
3. Failure: filters miss the event or the event aged out
Current organization audit-log search does not behave like free-text log search; use supported qualifiers. The default REST response focuses on the past three months, while the current audit-log window is broader and Git events are retained for only seven days. An incident playbook that waits two weeks before collecting Git events has already lost native evidence by design.
4. Failure: all evidence is retained only inside the account being investigated
A compromised enterprise owner or identity provider incident can make “log in to GitHub and inspect the log” unavailable or untrustworthy as the sole strategy. For enterprise workloads, external streaming/archive improves resilience. For smaller organizations, scheduled filtered exports and a write-restricted archive can implement the same principle at lower scale. The external system must itself have access control, retention, monitoring, and integrity checks.
5. Failure: policy exists in Markdown but nothing enforces it
A policy says “all default-branch changes require two reviewers,” but the repository has no ruleset or branch protection. An audit can prove the document exists, yet the control objective is not enforced. Repair is not to rewrite the sentence. First inspect the repository rules that target the default branch, then introduce enforcement in a staged disposable/non-production path, verify merge behavior, and only then update the control matrix to point at real enforcement.
REPO="OWNER/REPOSITORY"
gh api -H "X-GitHub-Api-Version: 2026-03-10" "repos/$REPO/rulesets" --jq '.[] | {id,name,target,enforcement,conditions,rules}'
6. Failure: bypass/exception has no owner or expiry
An exception with only “temporary production hotfix” cannot be reviewed. Who accepted the risk? Which repository/ref? Which control was bypassed? When should it close? What compensating evidence proves the change? The repair is an exception schema and automated expiry review, not a larger bypass group. If the bypass is still active after expiry, treat that as control drift.
7. Failure: administrators treat absence as proof
Several distinct conditions can produce no event: the action is outside the audit taxonomy; the event is older than retention; Git-event collection rules differ from web events; the export omits a class of Git events; the query is scoped to the wrong org/repository; the viewer lacks permission; a plan does not expose that telemetry; or the action occurred in an external system. State your conclusion as “no matching event was found under query Q, scope S, window T, and surface P,” not “the action never happened.”
8. Failure: enterprise policy overrides local intent
Organization admins may see a disabled setting and assume their role/token is broken when an enterprise policy actually fixes the value. Diagnose from the top of the policy hierarchy downward: enterprise policy → organization setting/configuration → repository setting/ruleset → workflow behavior. Do not grant ownership or create a PAT to work around inherited policy. Escalate to the enterprise policy owner with the exact resource and desired exception.
9. Security-sensitive and destructive actions in governance incidents
| Action | Why dangerous | Chapter treatment |
|---|---|---|
| Repository deletion/transfer | Changes ownership/availability and evidence location | Never mandatory; preserve evidence first |
| Branch/tag force update or history rewrite | Destroys/rewrites Git evidence and collaborators' history | Not used here |
| Ruleset/policy bypass | Weakens preventive control | Fixture/design only unless disposable and explicitly approved |
| Token/key creation | Introduces new credentials and audit scope | No new credential required |
| Secret handling | Can turn evidence collection into a leak | Never log raw credentials; minimize exported sensitive fields |
| Security configuration change | Can disable protections across repositories | Read-only/fixture in mandatory path |
10. Rate limits, export size, and evidence-pipeline reliability
Audit retrieval is not a data-warehouse query engine. The Enterprise Cloud organization audit-log REST endpoint currently has a dedicated limit of 1,750 queries per hour per user and IP. UI exports have size/time limits. Use narrow time ranges, supported qualifiers, pagination, and external streaming/archive for continuous analytics. For streams, GitHub's at-least-once model means duplicates are normal; deduplicate without dropping legitimately distinct events.
11. Recovery pattern
Incident correction record
- Evidence preserved: raw export + SHA-256 + query + retrieval time
- Scope confirmed: enterprise/org/repo/ref/resource
- Cause: wrong include=git filter for web ruleset event
- Correction: include=web; absolute UTC time window
- Current control state: ruleset active, expected conditions verified
- Exception state: none / or owner + expiry documented
- External retention: evidence vault object ID
- Independent verifier: second operator / review ticket
This is intentionally more rigorous than “fixed query.” The recovery closes the evidence gap and proves the control state after correction.
Knowledge check
Why can an audit API return 200 with an empty array and still represent a diagnostic failure?
HTTP 200 only says the request was valid. A wrong event family, time filter, repository, or action qualifier can make a logically incorrect investigation return no rows.
What should an incident responder preserve before changing a ruleset?
Raw audit/log evidence, current ruleset JSON, relevant Git refs/commits, permissions and timestamps, plus hashes/collection context. Mutation can otherwise destroy the before-state needed for diagnosis.
A policy document requires two reviewers but no rule enforces it. What is the actual failure?
The control is descriptive rather than preventive. The repair is to implement/test an appropriate GitHub enforcement control, not merely improve the wording.
Why is “no event found” weaker than “the action did not occur”?
Audit coverage, retention, filters, permissions, plan/deployment, event type, and external systems constrain what the search can observe.
What should happen when enterprise policy prevents an organization-level setting change?
Identify the inherited enterprise policy and escalate to its owner. Do not broaden credentials or attempt a local bypass as if the issue were authentication.
Summary
Governance diagnostics preserve evidence before changing state, distinguish query failure from control failure, account for retention/availability, and avoid turning an investigation into a privilege escalation. Lesson 5 integrates the chapter into a compact compliance-evidence packet with predictions, controlled changes, independent verification, exceptions, and retention.
Further reading — current primary sources
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.