Ketergantungan buta pada public package registry (seperti npmjs.com atau crates.io) membuka celah software supply chain attack, mulai dari pembajakan akun maintainer, dependency confusion, hingga injeksi kode berbahaya pada build metadata. Mengambil dependensi langsung dari Version Control System (Direct VCS) memotong perantara registry publik dan memberikan kendali penuh terhadap source code yang dikonsumsi pipeline CI/CD.

Anatomi Risiko: Registry Poisoning vs Direct VCS

Public registry umumnya menerima paket hasil kompilasi atau bundling tarball yang diunggah maintainer. Tidak ada jaminan build artifact tersebut identik 1:1 dengan kode sumber di repository Git publik (masalah reproduktibilitas). Penyerang yang mencuri API token maintainer dapat merilis versi baru berisi backdoor langsung ke registry tanpa menyentuh repository Git.

Dengan direct VCS, CI/CD menarik dependensi langsung dari repository Git target (misalnya GitHub, GitLab, atau self-hosted Gitea). Metode ini memastikan kode yang dieksekusi adalah commit yang diaudit, bukan artefak hasil modifikasi di layer registry.

Implementasi Commit Pinning Lintas Package Manager

Git tag bersifat mutable—maintainer atau penyerang dapat menghapus tag dan membuatnya ulang menunjuk ke commit hash berbeda. Keamanan sejati pada direct VCS mewajibkan full commit SHA pinning (40 karakter heksadesimal).

1. Go Modules

Secara default, Go mengambil source code langsung via Git/VCS. Untuk mengunci commit tertentu secara eksplisit tanpa proxy publik:

# Bypass Go proxy publik untuk modul internal/tertentu
export GOPRIVATE="github.com/org/*"

# Pin ke commit hash spesifik (pseudo-version)
go get github.com/org/crypto-core@a1b2c3d4e5f678901234567890abcdef12345678

Perintah ini memperbarui go.mod dengan pseudo-version dan mencatat cryptographic hash di go.sum untuk memvalidasi integritas source tree.

2. Cargo (Rust)

Gunakan field git dan rev pada Cargo.toml. Hindari penggunaan tag atau branch karena sifatnya yang dinamis.

[dependencies]
auth-lib = {
    git = "https://github.com/org/auth-lib.git",
    rev = "a1b2c3d4e5f678901234567890abcdef12345678"
}

3. npm / Yarn

Definisikan dependensi dengan format commit pinning langsung pada package.json:

{
  "dependencies": {
    "data-parser": "git+https://github.com/org/data-parser.git#a1b2c3d4e5f678901234567890abcdef12345678"
  }
}

Pastikan package-lock.json atau yarn.lock selalu di-commit ke repository untuk memvalidasi tree integritas seluruh sub-dependensi.

Isolasi Kredensial: Deploy Token Read-Only di CI/CD

Mengambil dependensi dari private Git repository membutuhkan akses autentikasi di pipeline CI. Jangan gunakan Personal Access Token (PAT) milik engineer individual. Terapkan prinsip least privilege menggunakan Project Deploy Token read-only.

Contoh konfigurasi otentikasi Git pada GitHub Actions menggunakan Deploy Key atau Fine-Grained Token:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Configure Git Credentials for Private Dependencies
        run: |
          # Paksa Git menggunakan HTTPS token isolasi alih-alih SSH interaktif
          git config --global url."https://x-access-token:${{ secrets.DEP_READ_ONLY_TOKEN }}@github.com/".insteadOf "https://github.com/"

      - name: Fetch and Verify Dependencies
        run: |
          # Contoh Cargo vendor lokal untuk validasi isolasi offline
          cargo vendor
          cargo check --frozen --offline

Flag --frozen dan --offline memastikan compiler tidak mencoba resolusi jaringan dinamis di luar lockfile yang sudah diverifikasi.

Otomatisasi Audit SBOM pada Pipeline CI

Mengambil dependensi direct VCS bukan berarti mengabaikan pelacakan kerentanan. Generate Software Bill of Materials (SBOM) format CycloneDX atau SPDX di setiap build CI untuk memetakan dependensi berbasis commit hash ke database CVE.

Implementasi step validasi SBOM menggunakan syft dan grype di pipeline CI:

      - name: Generate SBOM
        uses: anchore/sbom-action@v0
        with:
          format: cyclonedx-json
          output-file: build/sbom.cyclonedx.json

      - name: Scan SBOM for Vulnerabilities
        run: |
          curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
          grype sbom:build/sbom.cyclonedx.json --fail-on medium

Trade-off dan Mitigasi Operasional

  • Build Time: Mengunduh direct Git repository lebih lambat dibanding pre-built tarball registry. Solusi: Terapkan caching direktori modul/vendor di CI storage (misal: caching folder ~/.cargo/git atau $GOPATH/pkg/mod).
  • Transitive Dependencies: Package direct VCS tetap bisa menarik sub-dependensi dari registry publik jika repositori tersebut mendefinisikannya demikian. Solusi: Vendor direct dependencies (go mod vendor, cargo vendor) dan lakukan code review berkala pada lockfile diff.