Sửa triệt để lỗi ‘fatal: detected dubious ownership in repository’ với Git safe.directory

Git tutorial - IT technology blog
Git tutorial - IT technology blog

Bối cảnh & Nguyên nhân cốt lõi

Bạn vừa mount thư mục code từ máy host vào Docker container. Bạn gõ git status và nhận ngay một gáo nước lạnh:

fatal: detected dubious ownership in repository at '/workspace/my-app'
To add an exception for this directory, call:

	git config --global --add safe.directory /workspace/my-app

Tình huống này cũng rất quen thuộc khi bạn SSH vào server staging có 4-5 dev cùng dùng chung.

Repo không hề hỏng. Git cũng không bị lỗi. Đây là cơ chế bảo mật được thêm vào từ bản vá CVE-2022-24765 (tháng 4/2022).

Trước bản vá, Git luôn lùi dần lên các thư mục cha để tìm thư mục .git. Trên máy chủ nhiều user, kẻ xấu có thể tạo sẵn một repo giả ở thư mục dùng chung như /tmp hoặc /var/www. Trong file cấu hình .git/config đó, họ chèn hook độc hại hoặc cấu hình core.fsmonitor trỏ tới một script nguy hiểm. Khi bạn đứng ở thư mục con và gõ lệnh Git bất kỳ, mã độc sẽ lập tức chạy dưới quyền tài khoản của bạn.

Để bịt lỗ hổng, Git đặt ra quy tắc mới: User thực thi lệnh phải sở hữu chính thư mục repo đó.

Vấn đề phát sinh khi bạn dùng Docker. Mã nguồn trên máy host thuộc sở hữu của user bình thường (thường là UID 1000). Nhưng container lại chạy mặc định bằng root (UID 0). Hai UID lệch nhau hoàn toàn. Git lập tức chặn đứng thao tác để phòng ngừa rủi ro.

Kiểm tra phiên bản Git

Cơ chế safe.directory có sẵn từ Git 2.35.2. Đầu tiên, hãy kiểm tra phiên bản trên máy hoặc bên trong container:

git --version

Nếu phiên bản thấp hơn, bạn cần nâng cấp gói. Trên Ubuntu/Debian:

sudo apt update && sudo apt install -y git

Trên Alpine Linux (image phổ biến cho Docker):

apk update && apk add --no-cache git

4 Cách xử lý từ an toàn đến triệt để

Đừng vội copy bừa lệnh trên mạng. Bạn nên chọn giải pháp phù hợp với môi trường thực tế của mình.

1. Whitelist từng thư mục cụ thể (Khuyên dùng)

Cách đơn giản nhất là báo cho Git biết thư mục này tuyệt đối an toàn:

git config --global --add safe.directory /workspace/my-app

Lệnh này ghi một dòng vào file ~/.gitconfig của user hiện tại. Nếu đang đứng trong container chạy quyền root, file được ghi là /root/.gitconfig.

2. Cấu hình sẵn trong Dockerfile hoặc Compose

Khi build dev-container hoặc CI/CD runner (như GitLab CI, Jenkins), container dựng mới liên tục sẽ làm mất config. Hãy đưa thẳng vào Dockerfile:

FROM node:20-alpine

WORKDIR /app

# Cài git và whitelist thư mục làm việc
RUN apk add --no-cache git \
    && git config --global --add safe.directory /app

CMD ["npm", "run", "dev"]

Nếu dùng docker-compose.yml cho môi trường local dev, bạn có thể chạy lệnh này ở phần entrypoint hoặc command:

version: '3.8'
services:
  api:
    image: python:3.11-slim
    working_dir: /code
    volumes:
      - .:/code
    command: >
      sh -c "git config --global --add safe.directory /code &&
             python main.py"

3. Đồng bộ UID giữa Host và Container (Chuẩn bài nhất cho Dev)

Bản chất lỗi nằm ở sự lệch pha UID (1000 vs 0). Khắc phục tận gốc bằng cách ép container chạy bằng chính UID/GID của bạn:

docker run -it --rm \
  -u $(id -u):$(id -g) \
  -v $(pwd):/workspace \
  -w /workspace \
  node:20-alpine sh

Lợi ích kép: Git không còn báo lỗi dubious ownership. Đồng thời, các file do container sinh ra (như node_modules, cache) cũng không bị biến thành quyền root trên máy host.

4. Sửa quyền sở hữu thư mục trên Linux

Trên server dùng chung, lỗi thường do một đồng nghiệp lỡ gõ sudo git clone hoặc sudo git pull. Bạn chỉ cần trả lại quyền sở hữu cho tài khoản cá nhân:

sudo chown -R $USER:$USER /var/www/my-app

Cảnh báo: Tránh xa wildcard ‘*’

Nhiều câu trả lời trên Stack Overflow khuyên bạn chạy lệnh này cho tiện:

# NGUY HIỂM: TUYỆT ĐỐI TRÁNH TRÊN MÁY THẬT
git config --global --add safe.directory '*'

Dấu * vô hiệu hóa hoàn toàn cơ chế bảo vệ của CVE-2022-24765 trên mọi ngóc ngách của hệ thống. Bạn chỉ nên cân nhắc dùng nó bên trong container CI/CD chạy tạm thời rồi hủy ngay (ephemeral runner). Đừng bao giờ áp dụng trên máy cá nhân hay server production.

Kiểm tra và Dọn dẹp

Sau khi thiết lập, bạn nên kiểm tra lại xem Git đã nhận cấu hình hay chưa.

Xem danh sách safe.directory hiện tại

git config --global --get-all safe.directory

Nếu muốn kiểm tra vị trí file lưu config (system, global hay local), thêm cờ --show-origin:

git config --list --show-origin | grep safe.directory

Xác nhận trạng thái

Chạy thử lệnh quen thuộc trong thư mục dự án:

git status

Nếu Git hiển thị nhánh và commit bình thường mà không kèm cảnh báo đỏ, bạn đã hoàn tất.

Xóa đường dẫn không còn dùng

Khi xóa dự án cũ, bạn nên dọn dẹp cấu hình để file ~/.gitconfig luôn gọn gàng:

git config --global --unset-all safe.directory /workspace/my-app

Hiểu đúng cơ chế UID và safe.directory giúp bạn xử lý lỗi phân quyền trong 30 giây mà không cần đánh đổi tính an toàn của hệ thống.

Share: