GitHub là công cụ rất thuận tiện để lưu source code, quản lý phiên bản và cộng tác, nhưng chỉ một lần commit nhầm .env, API key, database password, private key hoặc file cấu hình production cũng có thể tạo ra sự cố bảo mật. Muốn đưa code lên GitHub an toàn, cần bảo vệ đồng thời quyền xem repository, secrets, Git history và tài khoản GitHub.
Nếu source code không được phép công khai, hãy dùng Private Repository.
Trước lần commit đầu tiên, tạo .gitignore để loại
.env, private key, credential file, file backup và dữ liệu nhạy cảm.
Secret nên được truyền qua environment variables, secret manager hoặc GitHub Actions Secrets,
không hard-code trong source.
Trước mỗi commit, kiểm tra bằng git status và git diff --cached.
Nếu đã lỡ commit credential, rotate/revoke credential trước;
chỉ xóa file khỏi commit mới là chưa đủ vì dữ liệu có thể vẫn nằm trong Git history.
Repository Private ngăn source code bị công khai cho toàn Internet, nhưng những người được cấp quyền vẫn có thể đọc và clone code theo quyền của họ. Vì vậy repository visibility chỉ là lớp bảo vệ đầu tiên. Bạn vẫn cần quản lý collaborator, tài khoản, token, máy tính cá nhân, CI/CD và Git history.
Source code thường bị lộ trên GitHub bằng những cách nào?
Phần lớn sự cố không bắt đầu từ việc GitHub tự động “làm lộ code”, mà từ cấu hình hoặc thao tác của người sử dụng.
- Tạo repository Public thay vì Private.
- Commit nhầm file
.env. - Hard-code API key trực tiếp trong source.
- Commit SSH private key hoặc certificate private key.
- Đưa file backup/database dump lên repository.
- Mời collaborator không còn cần quyền truy cập.
- Tài khoản GitHub bị chiếm quyền.
- Secret đã xóa ở file hiện tại nhưng còn trong Git history.
- CI/CD log vô tình in token ra console.
Bước 1 – Chọn Private Repository nếu source không được công khai
GitHub hiện phân biệt repository theo visibility. Với tài khoản thông thường, hai trạng thái quen thuộc nhất là:
Nếu đây là:
- Website của khách hàng.
- Source phần mềm thương mại.
- Backend nội bộ.
- Code chứa logic kinh doanh riêng.
- Dự án chưa phát hành.
thì Private Repository thường là lựa chọn hợp lý hơn Public.
Nếu code đã từng Public, hãy xem dữ liệu đó là đã có khả năng bị người khác xem hoặc sao chép. GitHub cũng cảnh báo việc chuyển repository Public sang Private không làm các public fork cũ tự động trở thành private.
Bước 2 – Tạo .gitignore trước lần commit đầu tiên
.gitignore nói với Git rằng
một số file hoặc thư mục không nên được đưa vào version control.
Ví dụ một dự án Node.js:
# Dependencies
node_modules/
# Environment variables
.env
.env.local
.env.production
.env.*.local
# Private keys / certificates
*.pem
*.key
*.p12
*.pfx
# Logs
*.log
logs/
# IDE / OS
.vscode/
.idea/
.DS_Store
# Build / cache
dist/
build/
.cache/
# Local database / backup
*.sqlite
*.db
*.sql
backup/
Danh sách này chỉ là ví dụ. Hãy điều chỉnh theo framework và dự án thực tế.
Một hiểu lầm rất nguy hiểm về .gitignore
Nếu file đã được Git track trước đó,
việc thêm file vào .gitignore
không tự động xóa file khỏi repository.
Ví dụ bạn đã từng:
git add .env
và commit, sau đó mới thêm:
.env
vào .gitignore,
thì secret có thể vẫn tồn tại trong commit/history trước đó.
Đây là lý do nên tạo .gitignore
trước commit đầu tiên.
Bước 3 – Không hard-code API Key, Password và Token
Code không nên chứa:
const API_KEY = "sk-live-xxxxxxxxxxxxxxxx";
const DB_PASSWORD = "my-super-secret-password";
Thay vào đó, hãy lấy giá trị từ environment variable.
const apiKey = process.env.API_KEY;
const dbPassword = process.env.DB_PASSWORD;
File local:
API_KEY=your_real_key_here
DB_PASSWORD=your_real_password_here
sẽ nằm trong .env,
và .env phải được ignore.
Nên commit .env.example thay cho .env
Để đồng đội biết ứng dụng cần biến môi trường nào, hãy tạo:
# .env.example
API_KEY=
DB_HOST=
DB_PORT=
DB_NAME=
DB_USER=
DB_PASSWORD=
File này chỉ thể hiện tên biến, không chứa credential thật.
COMMIT .env ✕
Bước 4 – Kiểm tra file trước khi commit
Trước khi chạy git commit,
hãy kiểm tra:
git status
Sau khi stage file, kiểm tra chính xác những thay đổi sẽ được commit:
git diff --cached
GitHub cũng khuyến nghị đây là cách hữu ích để xem diff sẽ đi vào commit.
Hạn chế lạm dụng git add .
Lệnh:
git add .
rất tiện, nhưng cũng dễ stage nhầm:
- File cấu hình local.
- Database backup.
- Debug output.
- Credential.
Với dự án chứa dữ liệu nhạy cảm, có thể stage rõ từng file:
git add src/
git add package.json
git add package-lock.json
git add .gitignore
Bước 5 – Quy trình đưa project mới lên GitHub an toàn
Ví dụ lệnh Git cơ bản
git init
git status
git add src package.json package-lock.json .gitignore .env.example
git diff --cached
git commit -m "Initial secure commit"
git branch -M main
git remote add origin YOUR_PRIVATE_REPOSITORY_URL
git push -u origin main
Hãy thay URL repository bằng repository Private mà bạn vừa tạo.
Bước 6 – Bảo vệ tài khoản GitHub bằng 2FA hoặc Passkey
Private Repository sẽ không còn nhiều ý nghĩa nếu tài khoản GitHub bị chiếm quyền.
GitHub khuyến nghị người dùng:
- Bật Two-Factor Authentication.
- Có thể sử dụng passkey.
- Kiểm tra SSH keys định kỳ.
- Kiểm tra authorized OAuth Apps và GitHub Apps.
- Thu hồi credential không còn sử dụng.
Đặc biệt với tài khoản sở hữu source code doanh nghiệp, không nên chỉ dựa vào một password.
Bước 7 – Dùng SSH Key hoặc Token đúng cách
GitHub hỗ trợ nhiều cách xác thực, trong đó SSH là lựa chọn phổ biến khi làm việc với Git từ máy tính.
Nguyên tắc quan trọng:
- Private SSH key nằm trên thiết bị của bạn.
- Không gửi private key qua chat/email.
- Không commit private key vào repository.
- Xóa SSH key cũ khỏi GitHub nếu máy đã mất hoặc không còn dùng.
Nếu dùng Personal Access Token
Token cũng phải được xem như password.
Không:
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxx
rồi commit file đó vào repository.
Với token, hãy ưu tiên phạm vi quyền tối thiểu cần thiết, thời hạn phù hợp và revoke khi không còn sử dụng.
Bước 8 – Quản lý Collaborator theo nguyên tắc “cần mới cấp”
Private Repository vẫn cho phép những người được cấp quyền đọc source.
Do đó định kỳ kiểm tra:
- Ai đang có quyền?
- Người đó còn làm trong dự án không?
- Agency/freelancer đã kết thúc hợp đồng chưa?
- Ứng dụng bên thứ ba nào đang có quyền repository?
Nếu repository thuộc tài khoản cá nhân, GitHub lưu ý collaborator của private personal repository có khả năng read và write. Nếu cần phân quyền chi tiết hơn cho nhiều thành viên, repository thuộc Organization thường phù hợp hơn để quản trị.
Bước 9 – Bảo vệ nhánh main
Private không chỉ cần chống người ngoài xem code. Cũng cần giảm nguy cơ một thành viên vô tình push sai hoặc xóa lịch sử quan trọng.
GitHub branch protection/rulesets có thể hỗ trợ:
- Require Pull Request trước khi merge.
- Require review.
- Require status checks.
- Block force push.
- Restrict người được push.
Workflow nhóm nên là:
thay vì mọi thành viên push thẳng lên main.
Bước 10 – Bật Secret Scanning và Push Protection khi phù hợp
Một trong những lớp bảo vệ quan trọng của GitHub là khả năng phát hiện credential bị hard-code.
Push Protection được thiết kế để chặn push chứa những secret được GitHub nhận diện trước khi chúng tới repository được bảo vệ.
Nó có thể phát hiện nhiều dạng credential như:
- API token.
- Access key.
- Credential của nhiều nhà cung cấp được hỗ trợ.
Không phải mọi chuỗi bí mật đều có thể được hệ thống tự động nhận diện. Developer vẫn phải kiểm tra file và tránh hard-code credential ngay từ đầu. Phạm vi tính năng cho private repository cũng phụ thuộc gói GitHub và tính năng bảo mật được bật.
Bước 11 – Secret của GitHub Actions phải để ở Secrets
Nếu repository sử dụng CI/CD, đừng viết credential trực tiếp vào workflow.
GitHub Actions hỗ trợ encrypted secrets ở mức:
- Repository.
- Environment.
- Organization trong phạm vi phù hợp.
Ví dụ workflow tham chiếu secret:
env:
API_TOKEN: ${{ secrets.API_TOKEN }}
Thay vì:
env:
API_TOKEN: "real-production-token-here"
GitHub cho biết Actions Secrets được mã hóa trước khi tới GitHub khi chúng được gửi qua UI hoặc REST API.
Những file tuyệt đối cần xem kỹ trước khi push
Đừng nhầm “Source Code” với “Secret”
Một private repository có thể chứa source code của dự án. Nhưng credential không nên được lưu trong source ngay cả khi repository Private.
Tư duy đúng:
SECRETS → ENVIRONMENT / SECRET MANAGER / ACTIONS SECRETS
Lý do: nếu một collaborator, token hoặc máy tính bị xâm nhập, việc không lưu credential trong code giúp giảm phạm vi thiệt hại.
Nếu đã lỡ commit .env hoặc API Key thì phải làm gì?
Đây là tình huống cần xử lý theo đúng thứ tự.
GitHub hiện khuyến nghị nếu dữ liệu là password, token hoặc credential, bước đầu tiên phải là revoke và/hoặc rotate. Một credential đã bị lộ không nên tiếp tục được tin cậy chỉ vì bạn đã xóa nó khỏi repository.
Nếu secret chỉ nằm trong commit cuối chưa push
Trường hợp này dễ xử lý hơn.
- Xóa secret khỏi source.
- Đảm bảo file được ignore nếu cần.
- Amend commit thay vì tạo thêm một commit chỉ để “xóa secret”.
Khi Push Protection chặn secret ở commit cuối, GitHub hiện hướng dẫn có thể sửa rồi amend commit.
git commit --amend --all
Sau đó kiểm tra lại trước khi push.
Tại sao xóa file khỏi repository vẫn chưa đủ?
Git lưu lịch sử các phiên bản.
Nếu file .env
đã tồn tại ở commit A,
sau đó bạn xóa ở commit B,
nội dung commit A vẫn có thể còn trong history.
GitHub xác nhận việc xóa một file không tự động xóa dữ liệu đó khỏi Git history.
Xóa file nhạy cảm khỏi toàn bộ Git History
GitHub hiện hướng dẫn sử dụng
git-filter-repo
cho các trường hợp cần loại dữ liệu nhạy cảm khỏi history.
Ví dụ xóa một file khỏi tất cả history:
git-filter-repo --sensitive-data-removal --invert-paths --path PATH-TO-SENSITIVE-FILE
Tuy nhiên, không nên chạy history rewrite một cách máy móc trên repository đang có nhiều người làm việc.
Việc rewrite có thể:
- Thay đổi commit hash.
- Ảnh hưởng Pull Request.
- Làm mất chữ ký commit/tag.
- Yêu cầu force push.
- Gây recontamination nếu đồng đội push lại history cũ.
Với repository doanh nghiệp, nên sao lưu và phối hợp toàn team trước khi rewrite history.
History đã rewrite vẫn có thể tồn tại ở nơi khác
Ngay cả sau khi rewrite, GitHub lưu ý dữ liệu cũ có thể còn:
- Trong clone của thành viên khác.
- Trong fork.
- Trong Pull Request reference.
- Trong một số cached view/reference trên GitHub.
Đây là một lý do nữa để rotate credential trước, không dựa vào history rewrite như biện pháp duy nhất.
Có nên commit source code lên GitHub Private không?
Có thể, và đây chính là một use case phổ biến của private repository.
Nhưng cần bảo vệ thêm:
- Tài khoản GitHub.
- Collaborator.
- Credential.
- Máy developer.
- CI/CD.
- Dependency.
Private Repository là access control cho source code, không phải hệ thống bảo mật duy nhất của dự án.
GitHub Private có miễn phí không?
GitHub hiện cho phép private repository trên tài khoản Free và hỗ trợ collaborator cho repository public/private.
Tuy nhiên một số tính năng bảo mật nâng cao, đặc biệt trên private organization repositories, có thể phụ thuộc gói hoặc license GitHub Code Security, Secret Protection hay GitHub Advanced Security.
Do đó không nên mặc định mọi tính năng đều có sẵn miễn phí trên mọi private repository.
Nên bật Dependabot không?
Có nếu dự án sử dụng package/dependency được hỗ trợ.
Dependabot hiện có thể hỗ trợ:
- Dependabot Alerts.
- Dependabot Security Updates.
- Dependabot Version Updates.
Nó không bảo vệ source code khỏi bị xem, nhưng giúp phát hiện dependency có lỗ hổng đã biết.
Một repository an toàn không chỉ cần “không lộ code” mà còn phải giảm rủi ro từ dependency bên thứ ba.
Có nên commit node_modules hoặc vendor không?
Trong phần lớn workflow thông thường,
không cần commit thư mục dependency đã cài đặt như node_modules.
Nên commit:
package.json.- Lock file như
package-lock.jsonkhi phù hợp.
Lock file giúp ghi rõ phiên bản dependency và GitHub cũng lưu ý lock file giúp dependency graph có dữ liệu đáng tin cậy hơn trong các ecosystem hỗ trợ.
Có nên đưa Database lên GitHub không?
Nếu database chứa dữ liệu thật của khách hàng, người dùng, đơn hàng hoặc thông tin nội bộ, không nên coi GitHub repository là nơi backup database mặc định.
Thay vào đó, nếu developer cần dữ liệu test, hãy tạo:
- Seed script.
- Fake data.
- Database schema.
- Migration.
và tránh đưa dữ liệu production thật vào repository.
Code frontend có thể giấu hoàn toàn không?
Đây là vấn đề khác với GitHub Private.
Code JavaScript được gửi xuống trình duyệt người dùng thì người dùng có thể quan sát bundle và request ở một mức độ nhất định.
Vì vậy:
- Không đặt database password trong frontend.
- Không đặt private API secret trong JavaScript client.
- Không dựa vào obfuscation như biện pháp bảo vệ credential.
Secret thực sự nên nằm ở backend hoặc hệ thống secret management phù hợp.
Architecture đúng cho API Secret
Thay vì:
Checklist trước lần Push đầu tiên
- ✓ Repository đã đặt Private nếu source không công khai.
- ✓ Có
.gitignore. - ✓
.envkhông được track. - ✓ Không có API key hard-code.
- ✓ Không có private key/certificate.
- ✓ Không có database production hoặc backup.
- ✓ Đã chạy
git status. - ✓ Đã chạy
git diff --cached. - ✓ Tài khoản GitHub đã có 2FA/passkey phù hợp.
- ✓ Collaborator chỉ gồm người cần truy cập.
Checklist bảo mật Repository cho nhóm Developer
- ✓ Private visibility.
- ✓ 2FA cho tài khoản.
- ✓ Quyền theo nguyên tắc least privilege.
- ✓ Pull Request review.
- ✓ Main branch protection/ruleset nếu gói hỗ trợ.
- ✓ Secret Scanning/Push Protection nếu phù hợp.
- ✓ Dependabot Alerts.
- ✓ GitHub Actions dùng Secrets thay vì hard-code.
- ✓ Thu hồi tài khoản/token của thành viên rời dự án.
- ✓ Review SSH keys và ứng dụng bên thứ ba định kỳ.
8 sai lầm dễ làm lộ Source Code hoặc Secret
Mức bảo vệ nên dùng theo loại dự án
Câu hỏi thường gặp
Đưa code lên GitHub Private có bị người ngoài xem không?
Private Repository không được công khai cho toàn Internet. Chỉ chủ sở hữu và những tài khoản/tổ chức được cấp quyền phù hợp mới có quyền truy cập. Tuy nhiên bạn vẫn phải bảo vệ tài khoản và quản lý collaborator.
GitHub Private có nên chứa file .env không?
Không nên. Credential nên tách khỏi repository bằng environment variable, secret manager hoặc GitHub Actions Secrets. Private Repository không phải lý do để hard-code password và API key.
Thêm .env vào .gitignore sau khi đã commit có đủ không?
Không. Nếu file đã được commit, nội dung có thể còn trong Git history. Trước hết hãy rotate/revoke credential nếu đó là secret, sau đó xử lý tracking và history tùy tình trạng repository.
Nếu lỡ push API key lên GitHub thì phải làm gì đầu tiên?
Rotate hoặc revoke API key ngay. Không chờ đến khi xóa Git history xong. GitHub hiện cũng khuyến nghị revoke/rotate credential là bước đầu tiên khi credential đã bị lộ.
Xóa file trên GitHub có xóa khỏi history không?
Không. Git giữ lịch sử commit. Nếu cần loại dữ liệu nhạy cảm khỏi toàn bộ history, GitHub hiện hướng dẫn quy trình riêng bằng git-filter-repo và cảnh báo việc rewrite history có nhiều tác động phụ.
Có nên bật Push Protection không?
Có nếu repository và gói của bạn hỗ trợ. Push Protection có thể chặn nhiều secret được nhận diện trước khi chúng được push, nhưng vẫn phải kết hợp với .gitignore, review diff và quản lý credential đúng cách.
GitHub Actions lưu API key ở đâu?
Hãy dùng GitHub Actions Secrets hoặc secret management phù hợp, sau đó tham chiếu secret trong workflow. Không hard-code token thật vào file YAML.
Kết luận: Repository Private chỉ là bước đầu tiên
Muốn đưa source code lên GitHub an toàn, hãy nghĩ theo bốn lớp:
1. SOURCE VISIBILITY: dự án riêng → repository Private.
2. SECRET MANAGEMENT: không hard-code API key, password hoặc private key.
3. ACCESS CONTROL: 2FA, collaborator phù hợp, branch protection và review.
4. LEAK PREVENTION: .gitignore, staged diff review, Secret Scanning và Push Protection khi có thể.
Nếu chỉ nhớ một nguyên tắc, hãy nhớ:
Hãy chuẩn hóa .gitignore,
.env.example,
quy tắc branch,
quyền collaborator và cách lưu secrets ngay khi tạo dự án.
Phòng ngừa một credential bị commit
đơn giản hơn rất nhiều so với phải rotate key,
rewrite toàn bộ Git history và phối hợp lại các clone/fork sau sự cố.
BEZON – Máy Tính BMT
Hotline/Zalo: 0922.47.6789
126–128 Nguyễn Chí Thanh, P. Tân An, TP. Buôn Ma Thuột, Đắk Lắk
