Le Duy Khuong

Chuỗi: ai-security-supply-chain · Phần 6

Năng suất & công cụ dev

Quản Lý Credentials Trong AI Infrastructure — Vượt Ra Ngoài .env

Malware LiteLLM harvest mọi thứ: environment variables, shell history, SSH keys. Nhưng credentials trong Vaultwarden vault thì không bị — encrypted at rest, không bao giờ plaintext trên disk.

2026-03-2614 phút đọcVI

Phần 6 của 786% hoàn thành

Quản Lý Credentials — Vượt Ra Ngoài .env

Khi malware LiteLLM chạy trên máy nạn nhân, nó quét tất cả những nơi credentials có thể tồn tại. Environment variables — đọc từ /proc/<pid>/environ. Shell history — ~/.bash_history, ~/.zsh_history. SSH keys — toàn bộ thư mục ~/.ssh/. File .env — quét mọi thư mục project.

Mọi thứ plaintext trên disk đều bị lấy.

Nhưng credentials lưu trong một password manager tự host — Vaultwarden — thì không. Encrypted at rest. Không bao giờ nằm plaintext trên filesystem. Vault database là một file SQLite được mã hóa AES-256 — dù attacker copy được file, không có master password thì cũng chỉ là dữ liệu vô nghĩa.

Câu chuyện này phân biệt rõ hai thế giới: credentials at rest (lưu trữ) vs credentials in flight (đang sử dụng). Và phần lớn developer chỉ bảo vệ cái đầu tiên mà quên cái thứ hai.


Credential Lifecycle — 5 Giai Đoạn, 5 Attack Vectors

Một credential — dù là API key, database password, hay SSH key — đều đi qua 5 giai đoạn trong vòng đời:

Tạo (Creation). Credential được generate. Nếu bạn tạo password yếu hoặc dùng lại password cũ, bạn đã thua từ bước đầu.

Lưu trữ (Storage). Credential cần một nơi an toàn. .env file trên disk? Bitwarden vault? GCP Secret Manager? Mỗi lựa chọn có trade-off khác nhau.

Tiêm vào (Injection). Credential cần được đưa vào application. Environment variable? Docker secret? Mount file? Mỗi phương pháp để lộ credential ở những nơi khác nhau.

Sử dụng (Usage). Application dùng credential để authenticate. Trong thời gian này, credential tồn tại trong process memory — và có thể bị dump.

Xoay vòng (Rotation). Credential cần được thay đổi định kỳ. Nếu bạn không có quy trình rotation, một credential bị lộ từ 6 tháng trước vẫn có thể được dùng hôm nay.

Mỗi giai đoạn là một cơ hội cho attacker. Malware LiteLLM khai thác giai đoạn 2 (file .env trên disk) và giai đoạn 3 (environment variables trong process).


Tại Sao .env Thất Bại

File .env được thiết kế cho local development. Nó đơn giản, mọi framework hỗ trợ, dễ hiểu. Nhưng khi hệ thống scale — đặc biệt AI infrastructure với 10-20 services mỗi cái cần API keys riêng — .env trở thành vấn đề.

Plaintext trên disk. .env không được mã hóa. Bất kỳ process nào có quyền đọc file đều thấy toàn bộ credentials. Malware, misconfigured backup, hay một docker cp nhầm thư mục — tất cả đều expose credentials.

Không audit trail. Ai đọc .env lần cuối? Ai sửa? Khi nào? Không có log. Không có history. Khi credential bị lộ, bạn không biết từ bao giờ.

Không rotation tự động. Đổi một API key trong .env nghĩa là SSH vào server, sửa file, restart service. Nhân với 15 services — mỗi lần rotation là nửa ngày manual work.

Dễ commit nhầm..gitignore.env, nhưng .env.production, .env.docker, .env-secret — những biến thể lạ — có thể lọt qua. Một lần commit nhầm vào git history = credential bị lộ vĩnh viễn (git history là forever).


Vault-Based Secret Management

Giải pháp: tách credentials ra khỏi filesystem và đưa vào một hệ thống chuyên dụng.

Self-hosted: Vaultwarden

Vaultwarden là implementation mã nguồn mở của Bitwarden server, viết bằng Rust, chạy nhẹ trên Docker. Nó cho phép:

# Lấy credential từ vault (CLI)
bw get password "ANTHROPIC_API_KEY"
 
# Inject vào environment
export ANTHROPIC_API_KEY=$(bw get password "ANTHROPIC_API_KEY")
docker compose up -d

Credential không bao giờ nằm trong file trên disk. Nó được pull từ vault, inject vào environment, và chỉ tồn tại trong process memory.

Cloud: GCP/AWS Secret Manager

Cho infrastructure lớn hơn:

from google.cloud import secretmanager
 
client = secretmanager.SecretManagerServiceClient()
response = client.access_secret_version(name="projects/my-project/secrets/anthropic-key/versions/latest")
api_key = response.payload.data.decode("UTF-8")

Credential được pull runtime, có audit log, có versioning, có automatic rotation.

Docker Secrets (Swarm)

services:
  litellm:
    secrets:
      - anthropic_key
    environment:
      - ANTHROPIC_API_KEY_FILE=/run/secrets/anthropic_key
 
secrets:
  anthropic_key:
    external: true

Mounted as file trong tmpfs — chỉ tồn tại trong memory, không trên disk.


Injection Pattern Cho Docker Compose

Pattern an toàn nhất cho Docker Compose không dùng Swarm secrets:

#!/bin/bash
# inject-and-run.sh — pull từ vault, inject, run, cleanup
 
# Pull secrets
export ANTHROPIC_API_KEY=$(bw get password "ANTHROPIC_API_KEY")
export DB_PASSWORD=$(bw get password "POSTGRES_PASSWORD")
export LITELLM_MASTER_KEY=$(bw get password "LITELLM_MASTER_KEY")
 
# Run with secrets in environment
docker compose up -d
 
# Cleanup — xóa khỏi shell environment
unset ANTHROPIC_API_KEY DB_PASSWORD LITELLM_MASTER_KEY

Credentials chỉ tồn tại trong Docker process environment — không trên disk, không trong shell history (vì không có lệnh echo hay export KEY=value nào).


"Secrets in Flight" — Vấn Đề Chưa Ai Giải Quyết Hoàn Toàn

Vault bảo vệ credentials at rest. Nhưng khi credential đang được sử dụng — "in flight" — nó vẫn vulnerable:

Environment variables trong container. docker inspect có thể đọc tất cả env vars của container. Nếu attacker có Docker socket access, toàn bộ secrets exposed.

Process memory. Credential nằm trong RAM của application. Memory dump = credential dump.

Shell history. Nếu ai đó paste credential vào terminal, ~/.zsh_history ghi lại. Malware LiteLLM harvest cả file này.

Logs. Application log credential vô tình? Đã xảy ra — nhiều lần, ở nhiều tổ chức.

Mitigation không phải loại bỏ hoàn toàn "in flight" exposure — mà là giảm thời gian và phạm vi exposure:

  • Short-lived tokens (OIDC) thay long-lived API keys
  • Per-service scoping: mỗi service chỉ có credentials nó cần
  • Audit logging: biết ai access credential nào, khi nào
  • Automatic rotation: credential bị lộ sẽ hết hạn tự động

AI Infrastructure — Credential Sprawl Đặc Biệt

AI infrastructure có vấn đề credential sprawl nghiêm trọng hơn bất kỳ domain nào khác.

Một AI server stack điển hình cần: API key cho mỗi LLM provider (Anthropic, OpenAI, Google), database password cho vector store, Redis password cho cache, master key cho API gateway, embedding service credentials, monitoring dashboard passwords, container registry tokens.

15-20 credentials cho một stack. Mỗi cái là một điểm mà attacker có thể khai thác.

Và AI agents làm vấn đề phức tạp hơn. Một agent có thể cần access nhiều services — LLM cho reasoning, database cho memory, search engine cho retrieval. Mỗi access cần credential riêng. Per-agent scoping trở nên cần thiết: agent A chỉ có API key cho Claude, agent B chỉ có database read access, không ai có access toàn bộ.

Nguyên tắc: một agent chỉ biết đúng những credentials nó cần. Không hơn. Nếu agent bị compromise — qua prompt injection hay dependency poisoning — blast radius giới hạn ở scope của agent đó.


Checklist Migration Từ .env Sang Vault

  1. Kiểm kê tất cả credentials hiện tại (grep -r "KEY|SECRET|PASSWORD|TOKEN" trong docker-compose files)
  2. Phân loại theo sensitivity: high (API keys, DB passwords), medium (monitoring passwords), low (non-secret config)
  3. Import high-sensitivity credentials vào vault đầu tiên
  4. Tạo injection script (pull từ vault → export → docker compose up)
  5. Test: verify services start thành công với vault-injected credentials
  6. Xóa .env files chứa high-sensitivity credentials
  7. Set rotation schedule: API keys mỗi 90 ngày, DB passwords mỗi 180 ngày
  8. Enable audit logging trong vault
  9. Document: secret nào ở đâu, rotation schedule, emergency revocation procedure

Bài tiếp — và cũng là bài cuối của series: Bảo Mật Trong Kỷ Nguyên AI Agent — Chúng Ta Chưa Sẵn Sàng. Nhìn toàn cảnh: khi AI agents trở thành infrastructure core, threat landscape thay đổi thế nào?

Đây là bài 6/7 trong series "Bảo Mật Trong Kỷ Nguyên AI Agent".

LDK

Le Duy Khuong

AI Transformation & Digital Strategy. Writing about agentic systems, engineering leadership, and building in public.