SovranCode
HomeCourses Git & GitHub GitHub Security
This device
Course contentsGitHub Security · 41 topics

1. Git Fundamentals

Git IntroductionGit Version ControlGit vs GitHubGit InstallationGit Working TreeGit RepositoryGit CommitGit .gitignoreGit Project: Learning Journal

2. Git History

Git LogGit DiffGit ResetGit RevertGit StashGit Project: Messy Repository

3. Branches & History

Git BranchGit MergeGit Merge ConflictsGit RebaseGit Cherry-PickGit TagsGit Project: Feature Branch

4. Remotes and GitHub

Git RemoteGitHub AuthenticationGitHub RepositoryGitHub ForkGitHub IssuesGitHub PagesGit Project: Two Clone Sync

5. GitHub Collaboration

GitHub Pull RequestsGitHub Code ReviewGit Branching WorkflowGitHub Branch ProtectionGitHub CollaborationGitHub ContributingGit Project: Reviewed Pull Request

6. Automation and Professional Git

GitHub ActionsGit InternalsGit RecoveryGitHub SecurityGit Project: Team Repository CIProject
Learn Git & GitHub40 complete · 1 planned

1. Git Fundamentals

Git IntroductionGit Version ControlGit vs GitHubGit InstallationGit Working TreeGit RepositoryGit CommitGit .gitignoreGit Project: Learning Journal

2. Git History

Git LogGit DiffGit ResetGit RevertGit StashGit Project: Messy Repository

3. Branches & History

Git BranchGit MergeGit Merge ConflictsGit RebaseGit Cherry-PickGit TagsGit Project: Feature Branch

4. Remotes and GitHub

Git RemoteGitHub AuthenticationGitHub RepositoryGitHub ForkGitHub IssuesGitHub PagesGit Project: Two Clone Sync

5. GitHub Collaboration

GitHub Pull RequestsGitHub Code ReviewGit Branching WorkflowGitHub Branch ProtectionGitHub CollaborationGitHub ContributingGit Project: Reviewed Pull Request

6. Automation and Professional Git

GitHub ActionsGit InternalsGit RecoveryGitHub SecurityGit Project: Team Repository CIProject
PREVIOUS LESSONGit Recovery
NEXT · UNIT 06 · PLANNEDGit Project: Team Repository CI
6. Automation and Professional Git 80 min

GitHub Security

Sign commits when the project requires it, keep tokens out of history, and rotate a leaked credential as a documented incident.

What you will leave with

You will distinguish a signed commit from a secure change, keep tokens in approved credential stores with narrow permissions, constrain a workflow token, and write a leak-response runbook whose first action is revocation. You will never paste a real token, private key, or secret value into this lesson.

Four security boundaries

GitHub Authentication proved who may talk to a host. Git .gitignore kept expected local files outside ordinary staging. Security adds signatures, credential lifecycle, automated least privilege, and incident response without pretending any one control solves all four.

Authentication

An SSH key, helper, or token proves an account may perform a network operation. It does not sign each commit automatically.

Signing

A private key signs exact commit or tag bytes. It does not grant GitHub repository access and does not encrypt content.

Secret storage

Credential helpers, agents, and approved secret stores keep values outside source history and routine logs.

Authorization

Token scopes, repository grants, workflow permissions, and branch rules limit what an authenticated identity may do.

“Verified” does not mean “safe”

A signed malicious or broken commit is still malicious or broken. Review, tests, dependency policy, and least privilege remain necessary.

What commit signatures prove

A Git commit id covers its tree, parents, author and committer metadata, message, and optional signature. Signing uses a private key to create evidence tied to those exact bytes. Change the parent, message, timestamp, or tree and the commit id—and signature target—changes.

# Inspect without changing configuration.
git config --show-origin --get gpg.format
git config --show-origin --get user.signingkey
git config --show-origin --get commit.gpgsign

# Inspect the latest commit's signature, if it has one.
git show --show-signature --no-patch HEAD
SIGNATURE PROVES

Possession and integrity

  • The matching private key signed this object.
  • The signed bytes have not changed.
  • A verifier can map the key to an allowed identity.
  • The evidence travels with the commit.
SIGNATURE DOES NOT PROVE

Safety or intent

  • The code is correct.
  • The author account was uncompromised.
  • The change was reviewed.
  • The key should still be trusted today.

Git supports OpenPGP, SSH, and X.509 signing formats. Use the format your project documents. This lab shows SSH signing because GitHub Authentication already introduced SSH keys; an organization may require a separate signing key, hardware-backed key, or OpenPGP instead.

Configure signing deliberately

# In a disposable repository, after your SSH signing key exists:
git config --local gpg.format ssh
git config --local user.signingkey ~/.ssh/id_ed25519.pub
git config --local commit.gpgsign true

git commit --allow-empty -m "Record signed release evidence"
git show --show-signature --no-patch HEAD
QUICK CHECK

Test what you learned

Type the command that enables automatic signing only in the current repository.

--local keeps this practice policy in the disposable repository. Do not turn on global signing until your key, agent, email, and project expectations are known. If the private key is passphrase-protected, the SSH agent should request or cache access; do not remove the passphrase to silence a prompt.

For GitHub to show an SSH-signed commit as Verified, add the public key to your account as a signing key and use an email identity GitHub can associate with the commit. If the same public key is also used for authentication, GitHub requires it to be registered for each purpose. The private key never leaves your machine or approved hardware.

Policy chooses the key

Personal projects may reuse an existing key. Teams may require separate authentication and signing keys, expiry, hardware protection, or organization-managed identities. Follow the repository policy rather than copying a global config.

Verify locally and on GitHub

# Sign only this commit, regardless of commit.gpgsign.
git commit -S -m "Document security boundary"

# Verify the object rather than trusting a badge screenshot.
git show --show-signature --no-patch HEAD
QUICK CHECK

Test what you learned

Type the command that shows the latest commit and verifies its signature without printing a patch.

Local SSH verification needs an allowed-signers file mapping identities to public keys. Configure that file according to your team policy with gpg.ssh.allowedSignersFile; do not commit a private key. Without a trusted mapping, Git can still show that a signature exists but may not label the signer trusted.

GitHub's Verified badge is platform evidence, not the object itself. GitHub checks the signature against keys and identity it knows. A local verifier may trust a different allowed-signers policy. Record the commit SHA and verification output; do not use a cropped badge screenshot as the only evidence.

Unsigned

No cryptographic signature is attached. That may be allowed unless branch rules or release policy require one.

Good signature

The bytes validate against the public key. Trust still depends on how that key was bound to an identity.

Unknown signer

The signature may be mathematically valid while the verifier lacks an approved identity mapping.

Bad signature

Do not merge or publish based on it. Preserve the object and investigate key, content, and tooling.

Treat tokens as expiring credentials

# These commands report account/session metadata, not the token value.
gh auth status
git remote -v

# Do NOT run this for screenshots, logs, or lesson evidence:
# gh auth token

# Do not put a token in a remote URL, command argument, file, or commit message.

Prefer GitHub CLI, Git Credential Manager, an SSH agent, or an organization-approved secret store. If a personal access token is required, prefer a fine-grained token when the operation supports it: select only required repositories, grant only required permissions, set a short expiration, and write a note naming the device or automation.

Scope

Read-only when possible. One repository instead of every repository. No administration grant for a clone.

Lifetime

Set an expiry and rotate before it. Delete credentials for retired machines and completed automation.

Storage

Use a helper or secret store. Never a remote URL, source file, shell script, issue, chat, or commit message.

Review

Periodically inspect active tokens, SSH keys, OAuth apps, deploy keys, and organization grants. Remove what you cannot explain.

Do not expose a token to prove you have one

gh auth status is suitable evidence. Commands that print a token value are not. Redact-and-screenshot workflows are fragile because terminals, logs, clipboard managers, and recordings may keep the original.

Constrain Actions credentials

GitHub Actions runs code on GitHub infrastructure. Every workflow should declare the smallest GITHUB_TOKEN permissions it needs. A read-only check usually does not need write access.

name: Read-only check

on: pull_request

permissions:
  contents: read

jobs:
  inspect:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: git diff --check

Store required values in GitHub Actions secrets or an approved external secret manager, then reference them through the workflow expression syntax. Do not place literal values in YAML. Do not echo secrets. Masking is defense in depth, not permission to transform, archive, or upload a credential.

Untrusted pull requests

Do not expose repository secrets to code from a fork. Treat checkout plus execution as running someone else's program.

Third-party actions

Review source and pin according to policy. An action receives the workspace and any credentials you grant it.

Environment gates

Production credentials may require environment approval. A passing test job should not automatically receive deployment power.

Logs and artifacts

Both can outlive a run and reach more readers. Never use them as secret transport.

Prevent secrets from entering Git

# Use a fake marker only. Never paste a real credential into a search command.
git grep -n 'EXAMPLE_TOKEN_DO_NOT_USE'
git log -S'EXAMPLE_TOKEN_DO_NOT_USE' --all --oneline

# Inspect the exact staged snapshot before committing.
git diff --cached --name-status
git diff --cached
QUICK CHECK

Test what you learned

Using the safe marker only, type the command that lists commits where EXAMPLE_TOKEN_DO_NOT_USE was added or removed.

Practice with the literal fake marker EXAMPLE_TOKEN_DO_NOT_USE. It grants nothing. Never paste a real credential into git grep, git log -S, terminal history, screenshots, or lesson answers. Provider secret scanning and approved security tools can identify token patterns without teaching contributors to repeat the value.

  1. 01
    Keep local values outside Git

    Ignore .env; commit only a value-free .env.example.

  2. 02
    Inspect the index

    Read every staged path and patch. A broad git add . is not a review.

  3. 03
    Scan before merge

    Use provider scanning and a repository-approved pre-commit or CI scanner.

  4. 04
    Minimize the credential

    A short-lived read token limits damage if prevention fails.

Respond to a leaked credential

If a real token, private key, password, or production connection string reaches Git history or logs, treat it as used by an attacker even if the repository was private and the commit existed briefly.

  1. 01
    Revoke or rotate

    Invalidate the credential at its provider first. Create a replacement only through the approved store and grant the minimum access.

  2. 02
    Record safe facts

    Time, repository, path, commit SHA, visibility, branches, forks, logs, and systems reached—never copy the secret into the incident report.

  3. 03
    Assess use

    Review provider audit logs and affected resources. Rotation stops future use; it does not explain what already happened.

  4. 04
    Remove current exposure

    Stop tracking the file, add a precise ignore rule, remove log artifacts, and replace real values with documented placeholders.

  5. 05
    Coordinate cleanup

    Decide whether history rewriting is required, identify every ref and clone, communicate new commit ids, and require fresh clones when policy says so.

  6. 06
    Prevent recurrence

    Add scanning, narrow permissions, improve setup docs, and close the incident with evidence.

Cleanup is not revocation

Deleting a file in a new commit or force-pushing rewritten history does not invalidate a copied credential. Revoke first. Cleanup limits continued discovery afterward.

Coordinate history cleanup

History cleanup changes commit ids for every rewritten descendant. Branches, tags, pull requests, forks, caches, release artifacts, and old clones may retain the original objects. Use the hosting provider's current sensitive-data-removal process and an approved rewriting tool. Do not improvise a force-push from a tutorial.

BEFORE REWRITE

Plan the boundary

  • Credential already revoked.
  • Affected paths and refs identified.
  • Owners and collaborators notified.
  • Protected evidence stored safely.
AFTER REWRITE

Close every copy path

  • Rewritten refs verified.
  • Hosted caches/support process handled.
  • Collaborators re-clone instead of merging old history.
  • Forks, artifacts, and logs reviewed.

Git Recovery teaches that old objects can remain locally even after refs move. That is exactly why history rewriting is coordinated cleanup, not a guarantee that every copy vanished.

Guided practice: signed, secret-free evidence

  1. 01
    Use a disposable repository

    Inspect signing config. If you already control an approved signing key, configure it locally; otherwise document the required policy without generating a throwaway identity.

  2. 02
    Create one signed commit

    Commit a value-free SECURITY.md. Record the SHA and local --show-signature output. Do not claim a badge proves review.

  3. 03
    Audit a fake marker

    Commit and remove EXAMPLE_TOKEN_DO_NOT_USE in a practice file. Use grep and pickaxe history to prove a later deletion leaves the earlier snapshot.

  4. 04
    Constrain a workflow

    Review a workflow with explicit permissions: contents: read. Confirm it prints no secret and runs no untrusted third-party action.

  5. 05
    Write the response order

    Revoke, record safe facts, assess, remove current exposure, coordinate cleanup, prevent recurrence.

Independent lab: security runbook

  1. In a disposable repository, add a value-free SECURITY.md describing supported reporting channels, signing policy, and what must never be committed. Do not include a real email, token, private key, customer record, or production URL.
  2. Inspect signing configuration. If an approved key already exists, configure signing locally and create one signed practice commit. Otherwise, write the exact setup your organization requires and state that no signature was fabricated.
  3. Add then remove the fake marker EXAMPLE_TOKEN_DO_NOT_USE across two commits. Prove the current tree is clean while git log -S still finds the earlier history.
  4. Review a small Actions workflow with explicit read-only permissions. Identify its event, code it executes, credentials available, and whether untrusted pull-request code can reach them.
  5. Write a seven-line incident card: credential type, revoke owner, safe evidence to record, audit-log location, current-tree containment, coordinated history-cleanup owner, and recurrence control. Use placeholders only.
  6. Finish with clean status. Your evidence may include key fingerprints and commit SHAs, never private key material or credential values. Do not create or revoke a real token solely for this lab.
Definition of done

You can verify what a signature proves, show that deleting a fake marker does not erase history, explain a workflow's credential boundary, and execute the leak-response order without copying a secret into new evidence.

Common security mistakes

Calling signed code safe

A signature proves key possession and object integrity, not correctness or review.

Turning on global signing blindly

Confirm key, agent, identity, verifier, and repository policy first.

Putting tokens in remote URLs

URLs leak through config, logs, process lists, and screenshots. Use a helper.

Trusting log masking

Encoding or transforming a value can bypass masks. Do not print secrets at all.

Deleting before revoking

History cleanup does not stop a copied credential from working.

Force-pushing without coordination

Old clones and refs can reintroduce exposed history. Follow an incident plan.

Lesson review

You can sign and verify commits under an explicit key policy, keep tokens narrow and outside Git, constrain workflow permissions, prevent secret commits, and respond to exposure with revocation before coordinated cleanup. The Team Repository CI project remains planned.

  • I can explain exactly what a valid signature proves—and what it does not prove.
  • I keep tokens in helpers or secret stores with narrow scope, expiry, and periodic review.
  • I inspect staged content and grant Actions only the permissions each job needs.
  • I revoke exposed credentials before repository cleanup and never repeat the value in incident evidence.

Related lessons

  • Git .gitignore — Ignore rules are the first defense against leaked secrets.
  • GitHub Authentication — Tokens belong in a credential helper, not a commit.
  • GitHub Actions — Workflow credentials need explicit least-privilege permissions.
  • Git Internals — A signature binds a key to exact commit-object bytes.
  • Git Recovery — Old objects can remain after refs move, so cleanup is not revocation.
KNOWLEDGE CHECK

Check your GitHub security model

Keep signing, authentication, secret storage, and incident response separate. Each protects a different boundary.

01What does a valid commit signature prove?
02How is a GitHub Verified badge different from Git's commit object?
03Where should an HTTPS personal access token live?
04What does adding .env to .gitignore do after .env was committed?
05What is the first response to a committed live token?
06How should a GitHub Actions workflow request permissions?
07Should you use a real token as the search text in a history-audit command?
PREVIOUS LESSONGit Recovery
NEXT · UNIT 06 · PLANNEDGit Project: Team Repository CI
ON THIS PAGEGitHub SecurityFour security boundariesWhat commit signatures proveConfigure signing deliberatelyVerify locally and on GitHubTreat tokens as expiring credentialsConstrain Actions credentialsPrevent secrets from entering GitRespond to a leaked credentialCoordinate history cleanupGuided practice: signed, secret-free evidenceIndependent lab: security runbookCommon security mistakesLesson reviewKnowledge checkRelated lessons
Course contents