소개
애플리케이션은 다른 프로젝트에서 작성한 라이브러리에 의존합니다. 자체 프로그램이 정상 동작하는 것처럼 보여도 유용한 라이브러리에 알려진 취약점이 있을 수 있습니다. 이 DeskLite 티켓 클라이언트는 Python HTTP 라이브러리 Requests의 영향을 받는 버전을 사용합니다.
고정된 오프라인 보안 권고를 읽고, 클라이언트가 실제로 가져오는 패키지를 업데이트하며, 기능과 버전 기록을 함께 확인합니다. 격리된 Python 환경, 설치 캐시, 보안 권고 두 개를 담은 교육용 스냅샷이 준비되어 있습니다. 패키지 관리나 Python 프로그래밍 경험은 필요하지 않습니다.
클라이언트 실행하고 패키지 확인하기
이 단계에서는 클라이언트의 현재 업무 동작을 확인하고 설치된 의존성의 위치를 찾습니다.
의존성은 애플리케이션이 사용하는 소프트웨어입니다. 이 클라이언트는 HTTP 요청을 위해 requests를 직접 사용합니다. Requests 자체는 그 작업의 일부에 다른 라이브러리인 urllib3를 사용합니다. 이 두 번째 관계를 전이 의존성이라고 합니다.
cd /home/labex/project/desklite-dependencies
.venv/bin/python은 이 프로젝트를 위해 준비된 격리된 Python 실행 파일입니다. 패키지는 시스템 Python과 분리되어 있습니다. 활성화 명령이나 전역 설치는 필요하지 않습니다. Git 실습에서 제공된 프로그램을 실행했던 것처럼 제공된 클라이언트를 실행하세요.
.venv/bin/python app.py
제목이 Printer offline인 원본 티켓이 예상됩니다. 프로그램은 보안 수정 전에도 동작합니다. 알려진 의존성 문제가 있다고 해서 모든 요청이 이미 실패하는 것은 아닙니다.
pip는 Python 패키지를 관리합니다. -m pip는 동일한 격리된 Python으로 패키지 관리자를 실행하도록 하며, show는 아무것도 변경하지 않고 메타데이터를 읽습니다.
.venv/bin/python -m pip show requests urllib3
Name, Version, Location을 찾으세요. Requests는 2.32.3, urllib3는 2.2.2여야 하며 패키지 위치는 이 프로젝트의 .venv 안이어야 합니다. 다른 Python 설치가 아니라 이 환경을 업데이트합니다.
오프라인 보안 권고 탐지 결과 읽기
이 단계에서는 검사기의 탐지 결과를 조치가 필요한 패키지 버전과 연결합니다.
준비된 실행 도구 course-deps는 2026-10-28 날짜의 고정 로컬 스냅샷으로 OSV-Scanner 2.7.0을 실행합니다. 의도적으로 작은 이 스냅샷에는 Requests와 urllib3에 대해 선택된 보안 권고 두 개가 들어 있습니다. 학습용 데이터이며 현재 운영 환경의 전체 취약점 피드가 아닙니다. 명령은 네트워크 요청을 보내지 않습니다.
준비된 잠금 기록을 지정하세요.
course-deps requirements.lock
requests 2.32.3, GHSA-9hjg-9r4m-mvj7, CVE-2024-47081, fixed: 2.32.4가 포함된 줄 다음에 Security findings: 1이 표시되어야 합니다. 두 ID는 서로 다른 보안 권고 체계에서 같은 문제를 가리킵니다.
이 보안 권고는 특정하게 조작된 URL과 저장된 클라이언트 자격 증명이 상호 작용할 때 발생할 수 있는 자격 증명 유출에 관한 것입니다. 여기서 공격을 재현하거나 해당 자격 증명을 설정할 필요는 없습니다. 제공된 호환 수정 버전을 설치하고 일반적인 요청을 유지하는 것이 과제입니다.
명령은 알려진 문제를 찾으면 의도적으로 1로 종료합니다. CHECK ERROR는 검사를 완료하지 못했다는 뜻으로 2로 종료하며, 안전하다는 증거가 아닙니다. 심각도 등급은 검토 우선순위를 정하는 데 도움이 되지만 이 애플리케이션이 이미 공격당했음을 보여주지는 않습니다.
보고서는 수정 버전을 알려줍니다. 다음으로 이 보고서를 설치와 재현에 사용하는 파일과 연결해 봅니다.
요구 사항과 설치 상태 구분하기
이 단계에서는 버전이 고정된 설치 목록과 확정된 환경의 기록을 읽습니다.
cat requirements.txt
각 줄은 package==version 형식입니다. 등호 두 개는 해당 패키지를 한 버전으로 고정합니다. 이 교육 과정의 목록에는 직접 의존성과 확정된 보조 패키지가 모두 포함되어 있어 오프라인으로 설치를 재현할 수 있습니다.
Requests는 2.32.3으로 고정되어 있습니다. 검사에서는 캐시에 있는 호환 수정 버전을 2.32.4로 보고했습니다. 관련 없는 줄은 모두 유지하세요.
cat requirements.lock
잠금 기록은 정확하게 확정된 패키지 버전을 설명합니다. 여기서는 모든 버전이 고정된 단순한 requirements 형식 파일입니다. 처음에는 설치 목록과 일치합니다. 업데이트 후에는 텍스트만 편집하여 패키지가 변경되었다고 주장하는 대신 실제 환경에서 이를 다시 생성합니다.
서로 다른 세 상태가 있습니다. requirements.txt에 있는 의도한 버전, .venv 안의 실제 패키지, requirements.lock의 확정된 기록입니다. 전달 시 모두 일치해야 합니다. 검사기는 지정한 파일을 읽으며, 실행 중인 애플리케이션이 해당 버전을 가져온다는 사실을 자동으로 입증하지는 않습니다.
/opt/labex-dependency-tools/wheels 아래의 캐시에는 준비된 초기 패키지와 수정 패키지가 있습니다. 이 캐시에서 설치하므로 온라인 버전 검색이나 의존성 충돌 해결은 필요하지 않습니다.
호환되는 수정 버전 설치하기
이 단계에서는 설치 목록을 업데이트하고 실제 프로젝트 환경에 수정 패키지를 설치합니다.
nano requirements.txt
requests==2.32.3만 requests==2.32.4로 변경하세요. 다른 버전 고정은 모두 유지하세요. Ctrl+O, Enter, Ctrl+X로 저장하세요.
이제 같은 환경의 패키지 관리자를 사용하세요. install은 설치된 패키지를 변경하고, -r requirements.txt는 지정된 설치 목록을 읽습니다. --no-index는 온라인 패키지 인덱스를 비활성화하며, --find-links는 pip에 준비된 wheel 파일의 위치를 알려줍니다. wheel은 미리 빌드된 Python 설치 패키지입니다.
.venv/bin/python -m pip install --no-index --find-links /opt/labex-dependency-tools/wheels -r requirements.txt
Pip은 Requests 2.32.3을 2.32.4로 교체하고 관련 없는 고정 패키지는 계속 요구 사항을 충족해야 합니다. 진행 메시지는 다를 수 있으므로 명시된 버전 변경으로 판단하세요. 일반 시스템 pip를 실행하면 다른 환경을 업데이트할 수 있으므로 사용하지 마세요.
.venv/bin/python -m pip show requests
Version: 2.32.4와 이 프로젝트의 .venv 안에 있는 위치가 예상됩니다. 목록을 저장하는 것만으로는 이 설치 상태가 확인되지 않습니다. 클라이언트는 실행할 때마다 패키지를 가져오는 일회성 프로그램이므로 이후 요청에서는 업데이트된 환경을 사용합니다.
잠금 기록 다시 생성하기
이 단계에서는 확정된 버전 기록이 실제 설치된 패키지를 설명하도록 합니다.
pip freeze는 환경에 설치된 패키지의 고정 버전을 출력합니다. 셸 연산자 >는 출력을 터미널 대신 파일에 쓰며, 파일의 이전 내용을 덮어씁니다. 여기서 대상은 구체적으로 프로젝트 잠금 기록입니다.
.venv/bin/python -m pip freeze > requirements.lock
출력이 파일로 들어가므로 보통 명령은 아무것도 출력하지 않습니다. 파일을 읽으세요.
cat requirements.lock
이제 Requests는 2.32.4여야 하며 다른 의존성 버전은 그대로여야 합니다. 순서나 대소문자는 달라도 기록된 패키지는 같을 수 있습니다.
선언된 의존성 관계를 확인하는 pip check로 패키지 호환성을 확인하세요.
.venv/bin/python -m pip check
No broken requirements found.가 예상됩니다. 이는 패키지 호환성을 확인하며, 애플리케이션의 업무 동작이나 가능한 모든 취약점을 확인하는 것은 아닙니다.
이제 설치 의도, 설치된 패키지, 확정된 기록이 일치합니다. 잠금 파일은 명령 실행을 입증하는 복사된 보고서가 아니라 실제 재현성을 위한 산출물입니다. 동일하게 정확한 고정 버전을 생성하는 유효한 동등 방법도 결과 요건을 충족합니다.
기능 회귀 검사 실행하기
이 단계에서는 라이브러리 업데이트 후에도 원래 요청과 응답이 유지되는지 확인합니다.
회귀는 변경 때문에 이전에 동작하던 기능이 깨지는 현상입니다. 교육 과정은 기존 클라이언트를 위한 작은 기능 검사인 test.sh를 제공합니다. 여기서는 이 검사를 실행하는 방법을 배웁니다. 테스트 작성은 나중에 다룹니다.
bash test.sh
예상 출력은 다음과 같습니다.
PASS: original ticket request and response.
검사는 실제로 로컬 티켓 서비스에 클라이언트를 실행하고 반환된 데이터를 비교합니다. 버전 문자열이 바뀌었다는 사실을 업무 성공으로 취급하지 않습니다.
클라이언트를 직접 한 번 더 실행하세요.
.venv/bin/python app.py
ID가 1이고 제목이 Printer offline인 원본 티켓이 예상됩니다. 클라이언트를 삭제하거나 의존성을 제거해서는 이 동작을 유지할 수 없습니다.
라이브러리는 디스크에서 업데이트되었으며 새로 시작한 이 클라이언트가 이를 가져옵니다. 장시간 실행되는 애플리케이션은 의존성 업데이트 후 별도의 통제된 재시작이 필요할 수 있습니다. 이 실습의 클라이언트는 매번 새로 실행됩니다. 마지막 단계에서는 정확한 잠금 기록으로 알려진 문제를 다시 확인합니다.
전달할 의존성 상태 다시 검사하기
이 단계에서는 고정 스냅샷 검사와 설치 패키지 및 업무 동작의 증거를 함께 확인합니다.
업데이트된 잠금 기록에 같은 오프라인 검사기를 실행하세요.
course-deps requirements.lock
No findings in the selected course snapshot.이 예상됩니다. 이는 선택된 보안 권고가 기록된 버전과 더 이상 일치하지 않는다는 뜻입니다. 스냅샷이 현재 또는 미래의 모든 문제를 포함한다고 입증하는 것은 아닙니다.
의도한 고정 버전과 실제 설치된 패키지를 검토하세요.
cat requirements.txt
.venv/bin/python -m pip show requests
Requests는 파일과 환경에서 모두 2.32.4여야 하며 관련 없는 고정 버전은 유지되어야 합니다. 이전 단계의 기능 검사는 업데이트된 클라이언트가 여전히 원래 요청을 수행한다는 별개의 요구 사항을 입증합니다.
완전한 수정에는 두 종류의 증거가 모두 필요합니다. 매니페스트만 편집하면 취약한 설치를 계속 사용할 수 있습니다. 설치를 업데이트하고 기록하지 않으면 나중에 안정적으로 재현할 수 없습니다. 검사기를 건너뛰거나 의존성을 삭제하는 것은 필요한 애플리케이션을 수정하는 대신 증거를 숨기는 것입니다.
조사 문서나 복사한 검사 보고서는 필요하지 않습니다. 전달할 결과물은 실제 업데이트된 패키지 환경, 정확한 고정 버전 기록, 유지된 업무 동작입니다.
요약
오프라인 보안 권고와 실제 설치된 Python 의존성을 연결하고, 준비된 캐시에서 호환되는 수정 패키지를 설치했으며, 의도한 버전 기록과 확정된 버전 기록을 동기화했습니다. 새로운 검사와 실제 기능 요청으로 명시된 교육용 스냅샷 범위 안에서 대상 문제가 수정되고 동작이 유지됨을 확인했습니다.



