Securing Your Git Repositories: Best Practices and Untrusted Sources
Secure Git repositories by keeping secrets out, limiting access, protecting branches, reviewing automation, and treating unknown code carefully.
Securing Your Git Repositories: Best Practices and Untrusted Sources
Securing your Git repositories is about more than keeping code private. A repository can contain secrets, executable hooks, supply chain risk, sensitive history, and configuration that affects every developer who clones it.
Good Git security practices help you avoid leaked credentials, unsafe automation, and accidental trust in code from unknown sources. The basics are simple, but they need to be applied consistently.
Protect Secrets Before They Reach Git
The safest secret is the one that never enters the repository. API keys, SSH private keys, cloud credentials, database passwords, tokens, and .env files should stay out of Git entirely.
Add local secret files to .gitignore:
.env
.env.*
*.pem
id_rsa
id_ed25519
Be careful with .env.example. That file is often useful, but it should contain fake placeholder values:
DATABASE_URL=postgres://user:password@localhost:5432/app
API_TOKEN=replace-me
Do not paste real values "just for testing." Git history remembers old versions even after you delete a line in a later commit.
If you accidentally commit a secret, treat it as exposed. Remove it from the current tree, rotate the credential in the service that issued it, and then decide whether history cleanup is required. Rewriting history can help reduce future exposure, but it does not guarantee the secret was never copied.
Teams should also use secret scanning. Many hosted Git platforms offer scanning for common token patterns. Local pre-commit tools can catch mistakes earlier, before a push reaches the server.
For related operational patterns, see mastering environment variables for configuration and secrets.
Lock Down Access and Branch Changes
Repository security starts with access control. Give people the least access they need. Someone who only reviews code probably does not need admin rights. A CI service account probably does not need permission to rewrite branches.
Review these settings regularly:
- Repository admins and owners.
- Collaborators with write access.
- Deploy keys and machine users.
- Personal access tokens used by automation.
- Webhooks that receive repository events.
- Branch protection rules.
Protected branches are one of the most useful controls. For important branches like main, require pull requests, status checks, and review before merging. Disable force pushes unless your team has a very specific reason to allow them.
Signed commits or signed tags can also help in higher-trust environments. They do not make code safe by themselves, but they can prove that a commit or release tag was created by a key your team recognizes.
Use tags carefully for releases. If a deployment process trusts tags, restrict who can create or move them. A moved release tag can confuse audits and deployments.
Be Careful with Untrusted Repositories
Cloning code from an untrusted source is common. Running it immediately is the risky part. A Git repository can include build scripts, package lifecycle scripts, Makefiles, containers, CI configuration, and instructions that execute code on your machine.
Before running anything, inspect the repository:
git clone --no-checkout https://example.com/project.git
cd project
git log --oneline -5
git status
Then check high-risk files:
- Shell scripts such as
install.shorbootstrap.sh. - Package scripts in
package.json. - CI files under
.github/workflows/,.gitlab-ci.yml, or similar paths. - Dockerfiles and compose files.
- Makefiles.
- Language-specific dependency manifests.
Do not run curl | bash setup commands from a random README. If a project requires an installer, download it, read it, and run it in a disposable environment if possible.
Git hooks deserve special mention. Hooks in .git/hooks/ are not normally transferred as active hooks when you clone a repository. That is good. But a repository may include scripts that install hooks for you. Read those scripts before running them because hooks can execute during commits, merges, rebases, and pushes.
For unknown code, use isolation. A temporary virtual machine, container, or locked-down development environment reduces the blast radius if a script behaves badly. Do not mount your SSH keys, cloud credentials, or production kubeconfig into an environment used for untrusted code.
Keep Repository History and Files Clean
Security is easier when the repository is tidy. Large binary files, generated archives, vendored secrets, and old config dumps make review harder and increase risk.
Use .gitignore for local files and .gitattributes for file handling rules. For example:
*.sh text eol=lf
*.png binary
*.jpg binary
If your project needs large files, consider whether Git Large File Storage is appropriate. Standard Git is not ideal for huge build artifacts or media files. Storing them directly can slow clones and make sensitive file cleanup harder.
Review pull requests for security-sensitive changes, not just application logic. Watch for:
- New credentials or tokens.
- New network calls in scripts.
- Dependency source changes.
- New CI permissions.
- Changes to deployment scripts.
- Broad
.gitignorechanges that hide important files.
Also pay attention to submodules. They point to external repositories and specific commits. If your project uses them, review submodule URLs and updates carefully.
When to Involve a Professional
Bring in a security engineer, DevOps lead, or incident response owner if a secret was pushed to a public repository, a protected branch was force-pushed unexpectedly, or an unknown contributor changed CI or deployment automation.
You should also get help if you suspect repository history was tampered with. Preserving evidence may matter more than cleaning up quickly, especially in a company environment.
Securing Git repositories comes down to disciplined trust. Keep secrets out, limit access, protect important branches, and inspect untrusted code before running it. Those habits prevent most repository security problems before they become incidents.