LabHub

Blog

Security vulnerability action playbook: OS package, container image, runtime hardening

한국어English日本語

Entering

When a security scanner pours out a list of CVEs, it becomes difficult to know where to start. The important thing is not to immediately fix all vulnerabilities, but to have a process to prioritize based on risk, take systematic action, and prevent recurrence.

In this article, we present a practical playbook covering OS package vulnerability patching, container image security, and runtime hardening.


1. Vulnerability response process overview


┌─────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 발견 │ → │ 분류 │ → │ 조치 │ → │ 검증 │ → │ 보고 │
Scanning │ │ Triage │ │ Remediate│Verify │ │ Report└─────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘

SeverityCVSS scoreAction DeadlineExample
Critical9.0~10.024~72 hoursRCE, authentication bypass
High7.0~8.97 daysEscalation of privilege, information leakage
Medium4.0~6.930 daysXSS, Denial of Service
Low0.1~3.990 days or next regular patchInformation disclosure (limited)

Core Principle: Do not judge only the CVSS score, but comprehensively judge Exploit Possibility (EPSS), Internet Exposure, and Importance of Affected Assets.


2. OS package vulnerability management

2.1 Vulnerability scan

# RHEL / Rocky - 보안 업데이트 확인
dnf updateinfo list security
dnf updateinfo list --sec-severity=Critical
dnf updateinfo info RHSA-2026:1234

# Ubuntu - 보안 업데이트 확인
apt update
apt list --upgradable 2>/dev/null | grep -i security

# 설치된 패키지의 CVE 확인 (Trivy)
trivy rootfs --severity CRITICAL,HIGH /

# OpenSCAP 스캔 (컴플라이언스)
oscap xccdf eval \
  --profile xccdf_org.ssgproject.content_profile_cis \
  --results results.xml \
  --report report.html \
  /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

2.2 Patch application procedure

#!/usr/bin/env bash
# patch-os.sh - OS 보안 패치 적용 스크립트
set -euo pipefail

LOG_FILE="/var/log/security-patch-$(date +%Y%m%d).log"
SNAPSHOT_NAME="pre-patch-$(date +%Y%m%d-%H%M%S)"

log() { printf '[%s] %s\n' "$(date +%T)" "$1" | tee -a "$LOG_FILE"; }

# 1단계: 스냅샷/백업
log "=== 패치 시작 ==="
log "스냅샷 생성: $SNAPSHOT_NAME"
# LVM 스냅샷 (해당 시)
# lvcreate -L 10G -s -n "$SNAPSHOT_NAME" /dev/vg0/root

# 2단계: 현재 상태 기록
rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | sort > /tmp/packages-before.txt

# 3단계: 보안 업데이트만 적용
log "보안 업데이트 적용 중..."
if command -v dnf &>/dev/null; then
  dnf update --security -y 2>&1 | tee -a "$LOG_FILE"
elif command -v apt-get &>/dev/null; then
  apt-get update
  apt-get upgrade -y -o Dpkg::Options::="--force-confold" 2>&1 | tee -a "$LOG_FILE"
fi

# 4단계: 변경된 패키지 목록
rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | sort > /tmp/packages-after.txt
diff /tmp/packages-before.txt /tmp/packages-after.txt > /tmp/packages-diff.txt || true
log "변경된 패키지:"
cat /tmp/packages-diff.txt | tee -a "$LOG_FILE"

# 5단계: 서비스 재시작 필요 여부 확인
if command -v needs-restarting &>/dev/null; then
  log "재시작 필요 서비스:"
  needs-restarting -s 2>&1 | tee -a "$LOG_FILE"
  if needs-restarting -r 2>&1 | grep -q "Reboot is required"; then
    log "WARNING: 커널 업데이트로 리부팅 필요"
  fi
fi

log "=== 패치 완료 ==="

2.3 Automatic security update settings

RHEL/Rocky

# dnf-automatic 설치·설정
dnf install -y dnf-automatic

# /etc/dnf/automatic.conf
# [commands]
# apply_updates = yes
# upgrade_type = security  # 보안 업데이트만

systemctl enable --now dnf-automatic-install.timer

Ubuntu

# unattended-upgrades 설정
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades

# /etc/apt/apt.conf.d/50unattended-upgrades
# Unattended-Upgrade::Allowed-Origins {
#   "${distro_id}:${distro_codename}-security";
# };
# Unattended-Upgrade::Automatic-Reboot "false";
# Unattended-Upgrade::Mail "admin@example.com";

2.4 Patch Management Checklist


3. Container image security

3.1 Comparison of image scanning tools

toolsLicenseFeaturesCI/CD integration
TrivyOSS (Apache-2.0)OS + language package + IaC + SecretGitHub Actions, GitLab CI
GrypeOSS (Apache-2.0)SBOM-based scanningCLI-centric
Snyk ContainerCommercial (Free Plan)Developer-friendly Fix PRMost CI
Prisma CloudcommercialAll CNAPPEnterprise CI
AWS ECR ScanningIncludes AWSInspector-basedAWS Native

3.2 Practical use of Trivy

# 이미지 스캔 (Critical + High만)
trivy image --severity CRITICAL,HIGH myapp:latest

# SBOM 생성
trivy image --format spdx-json -o sbom.json myapp:latest

# 취약점이 있으면 빌드 실패 (CI용)
trivy image --exit-code 1 --severity CRITICAL myapp:latest

# .trivyignore - 허용된 취약점 (예외 처리)
# CVE-2024-XXXX  # 해당 코드 경로 미사용, 2026-04-01까지 예외

3.3 Writing a secure Dockerfile

# 1. 최소 베이스 이미지 사용
FROM cgr.dev/chainguard/python:latest-dev AS builder
# 또는 distroless, Alpine, UBI-micro

# 2. 빌드 의존성과 런타임 분리 (멀티스테이지)
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
COPY . .

FROM cgr.dev/chainguard/python:latest
WORKDIR /app
COPY --from=builder /install /usr/local
COPY --from=builder /app .

# 3. non-root 사용자 (Chainguard은 기본 non-root)
# 일반 이미지의 경우:
# RUN addgroup -S app && adduser -S app -G app
# USER app

# 4. 불필요한 패키지 제거, 캐시 정리
# (멀티스테이지로 해결)

# 5. 건강 검사
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]

ENTRYPOINT ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]

3.4 Base image selection guide

Image TypesizeNumber of vulnerabilitiespackage managershellRecommended use
ubuntu:24.04~78MBmiddleaptbashuniversal
alpine:3.20~7MBlowapkashlightweight service
distroless~20MBvery lowNoneNoneProduction Runtime
chainguard~15MBalmost 0apk (dev only)None (dev only)Focus on security
ubi-micro~35MBlowNoneNoneRequires RHEL Compatibility
scratch0MB0NoneNoneGo binary

3.5 CI/CD pipeline integration

# GitHub Actions 예시
name: Container Security
on:
  push:
    branches: [main]
  pull_request:

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Trivy vulnerability scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          severity: CRITICAL,HIGH
          exit-code: 1
          format: sarif
          output: trivy-results.sarif

      - name: Upload scan results
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: trivy-results.sarif

      - name: Generate SBOM
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          format: spdx-json
          output: sbom.spdx.json

      - name: Upload SBOM
        uses: actions/upload-artifact@v4
        with:
          name: sbom
          path: sbom.spdx.json

4. Runtime hardening

4.1 Container runtime security

Docker hardening

# /etc/docker/daemon.json
{
  "userns-remap": "default",
  "no-new-privileges": true,
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2",
  "live-restore": true,
  "icc": false,
  "default-ulimits": {
    "nofile": { "Name": "nofile", "Hard": 65535, "Soft": 65535 }
  }
}

Security options when running containers

docker run -d \
  --name myapp \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=100m \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  --security-opt no-new-privileges:true \
  --security-opt seccomp=default.json \
  --pids-limit 100 \
  --memory 512m \
  --cpus 1.0 \
  --user 1000:1000 \
  myapp:latest

Kubernetes Pod Security

# Pod Security Standards - Restricted 프로파일
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: myapp:latest
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ['ALL']
      resources:
        limits:
          memory: 512Mi
          cpu: '1'
        requests:
          memory: 256Mi
          cpu: '0.5'
      volumeMounts:
        - name: tmp
          mountPath: /tmp
  volumes:
    - name: tmp
      emptyDir:
        sizeLimit: 100Mi

4.2 Kubernetes cluster hardening checklist

areaItemCommand/Settings
CertificationBlock anonymous access--anonymous-auth=false
Is itEnable RBAC--authorization-mode=RBAC
APINodeRestriction Admission--enable-admission-plugins=NodeRestriction
EtcdEncryption Settings--encryption-provider-config
NetworkApply NetworkPolicyCalico/Cilium Network Policy
PodPSA (Pod Security Admission)in the namespaceenforce: restricted
SecretExternal Secret ManagerVault, AWS Secrets Manager
ThanksAudit logging--audit-log-path, --audit-policy-file
ImageSignature VerificationCosign + Admission Webhook
RuntimeSeccomp/AppArmor ProfilePod securityContext

4.3 Network policy example

# 기본 거부 정책 (deny-all)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

---
# 앱 특정 허용 정책
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-app-traffic
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: nginx-ingress
      ports:
        - port: 8080
          protocol: TCP
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - port: 5432
          protocol: TCP
    - to: # DNS 허용
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53
          protocol: UDP
        - port: 53
          protocol: TCP

5. Playbook for each vulnerability response scenario

Scenario 1: Critical CVE Emergency Patch

1. [즉시] CVE 공지 확인 → 영향받는 패키지·버전 식별
2. [1시간] 자산 인벤토리에서 영향 범위 파악
3. [2시간] 패치 가용 여부 확인
   ├── 패치 있음 → 스테이징 적용 → 테스트 → 프로덕션 롤링
   └── 패치 없음 → Workaround 적용 (WAF, 설정 변경, 서비스 격리)
4. [24시간] 프로덕션 패치 완료
5. [48시간] 스캔으로 조치 검증 → 보고서 작성

Scenario 2: Container image vulnerability

1. 이미지 스캔 결과 확인 (Trivy/Snyk)
2. 취약점 분류:
   ├── OS 패키지 → 베이스 이미지 업데이트
   ├── 언어 라이브러리 → dependency 업데이트
   └── 설정 문제 → Dockerfile 수정
3. 이미지 재빌드 + 스캔 재실행
4. 스테이징 배포 → E2E 테스트
5. 프로덕션 롤링 업데이트
6. 이전 이미지 태그 비활성화

Scenario 3: Runtime breach detection response

1. [즉시] 알림 확인 (Falco, 감사 로그)
2. [즉시] 해당 Pod/컨테이너 격리 (NetworkPolicy deny-all)
3. [1시간] 포렌식 데이터 수집:
   - 컨테이너 프로세스 목록, 네트워크 연결
   - 감사 로그, 런타임 이벤트 로그
   - 이미지 레이어 분석
4. [4시간] 침입 경로 파악 → 취약점 조치
5. [24시간] 클린 이미지로 재배포
6. [1] 사후 분석 보고서 + 재발 방지 대책

6. Security scan automation architecture

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  코드 푸시   │ → │  CI 파이프라인 │ → │  이미지 빌드  │
└─────────────┘    └──────┬──────┘    └──────┬──────┘
                          │                   │
                   ┌──────▼──────┐    ┌──────▼──────┐
SAST 스캔   │    │  이미지 스캔  │
                     (Semgrep)  (Trivy)                   └──────┬──────┘    └──────┬──────┘
                          │                   │
                   ┌──────▼───────────────────▼──────┐
                   │         결과 집계 + 판정          │
                      (Critical → 빌드 실패)                      (High → 경고 + Jira 생성)                   └──────────────┬──────────────────┘
                   ┌──────────────▼──────────────────┐
                   │  레지스트리 푸시 (통과 시에만)                   └──────────────┬──────────────────┘
                   ┌──────────────▼──────────────────┐
                   │  정기 스캔 (주간, 레지스트리 전체)                   └─────────────────────────────────┘

7. Compliance mapping

frameworkRelated RequirementsResponse from this playbook
CIS BenchmarkOS·Docker·K8s benchmarkSection 2, 4
NIST 800-53SI-2 (Flaw Remediation)Section 2 (Patch Management)
PCI DSS 4.06.3 (Vulnerability identification/action)Full process
SOC 2CC7.1 (Monitoring), CC8.1 (Change Management)Section 5, 6
ISMS-P2.10 (System/Service Security Management)All

8. Toolchain Recommendation

Essential tools

UseOSScommercial
image scanTrivy, GrypeSnyk, Prisma Cloud
OS ComplianceOpenSCAP, LynisQualys, Tenable
runtime securityFalcoSysdig Secure
Create SBOMSyft, TrivyAnchore
Secret ScanGitleaks, TruffleHogGitGuardian
SASTSemgrep, CodeQLSonarQube, Checkmarx
image signatureCosign (Sigstore)Docker Content Trust
Policy EngineOPA/Gatekeeper, KyvernoStyra DAS
코드 단계: Gitleaks (시크릿) + Semgrep (SAST)
빌드 단계: Trivy (이미지 스캔) + Syft (SBOM)
배포 단계: Cosign (이미지 서명) + Kyverno (정책)
런타임:   Falco (이상 탐지) + 감사 로그

9. Report template

Vulnerability Action Report

# 보안 취약점 조치 보고서

## 개요

- 보고일: YYYY-MM-DD
- 작성자: 보안 운영팀
- 대상 기간: YYYY-MM-DD ~ YYYY-MM-DD

## 요약

| 심각도   | 발견 | 조치 완료 | 예외 처리 | 미조치 |
| -------- | ---- | --------- | --------- | ------ |
| Critical | 3    | 3         | 0         | 0      |
| High     | 12   | 10        | 2         | 0      |
| Medium   | 45   | 30        | 5         | 10     |

## Critical 취약점 상세

### CVE-YYYY-XXXXX

- 영향: [설명]
- 영향 자산: [서버/이미지 목록]
- 조치: [패치 버전/설정 변경]
- 조치일: YYYY-MM-DD
- 검증: [스캔 결과 첨부]

## 예외 처리 목록

| CVE            | 사유                  | 보완 조치   | 만료일     |
| -------------- | --------------------- | ----------- | ---------- |
| CVE-YYYY-XXXXX | 해당 코드 경로 미사용 | WAF 룰 추가 | YYYY-MM-DD |

## 개선 권고사항

1. [구체적 개선 사항]
2. [구체적 개선 사항]

10. Actual inspection checklist

OS Security

Container Security

Kubernetes Security


Finish

Security is not a one-time action, but a continuous process. Summarize the core of this playbook in three lines.

  1. Automation: Prevent manual omission by embedding scan, patch, and verification into CI/CD.
  2. Layered defense: Establish an in-depth defense strategy that covers OS, image, runtime, and network.
  3. Response system: Repeat the cycle of discovery → classification → action → verification → reporting, and maintain SLA.

Perfect security is impossible, but through systematic operation risk can be reduced to a manageable level.

Quiz

Q1: What is the main topic covered in "Security vulnerability action playbook: OS package, container image, runtime hardening"?

We organize a practical security operation playbook that covers everything from CVE discovery to action, verification, and reporting, OS package vulnerability patching, container image security, and runtime hardening.

Q2: What is Entering? When a security scanner pours out a list of CVEs, it becomes difficult to know where to start. The important thing is not to immediately fix all vulnerabilities, but to have a process to prioritize based on risk, take systematic action, and prevent recurrence.

Q3: Explain the core concept of Runtime hardening. 4.1 Container runtime security Docker hardening


bash /etc/docker/daemon.json "userns-remap": "default", "no-new-privileges": true, "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" "storage-driver": "overlay2", "live-restore": true, "icc": false, "defa...

Q4: What are the key aspects of Playbook for each vulnerability response scenario?

Scenario 1: Critical CVE Emergency Patch

  [1시간] 자산 인벤토리에서 영향 범위 파악 [2시간] 패치 가용 여부 확인 ├── 패치 있음 → 스테이징 적용
  → 테스트 → 프로덕션 롤링 └── 패치 없음 → Workaround 적용 (WAF 룰, 설정 변경, 서비스 격리) [24시간]
  프로덕션 패치 완료 [48시간] 스캔으로 조치 검증 → 보고서 작성 [즉시] 알림 확인 (Falco, 감사 로그)
  [즉시]...

Q5: How does Toolchain Recommendation work? Essential tools Recommended minimum configuration


코드 단계: Gitleaks (시크릿) + Semgrep (SAST)
  빌드 단계: Trivy (이미지 스캔) + Syft (SBOM) 배포 단계: Cosign (이미지 서명) + Kyverno (정책)
  런타임: Falco (이상 탐지) + 감사 로그

Comments

No comments yet.

Sign in to leave a comment