chore: 의존성 업그레이드 및 보안 취약점 해소 (npm audit 38 → 2) - #47
Merged
Conversation
- pydantic 2.11.7 → 2.13.4 - pydantic-settings 2.1.0 → 2.14.2 - python-dotenv 1.0.0 → 1.2.2 - yfinance 0.2.65 → 1.5.2 yfinance는 메이저 업그레이드지만 호출부(app/utils/data_fetcher.py)가 auto_adjust=True를 명시적으로 전달하고 있어, 1.x에서 바뀐 기본값의 영향을 받지 않는다. AAPL/005930.KS 2023-01-01~2023-06-30 구간을 0.2.65와 1.5.2로 각각 조회해 비교한 결과 바 개수·날짜 동일, 종가 최대 상대차 0.000034% (부동소수점 오차 수준)로 확인했다. backtesting==0.3.3 핀과 그에 묶인 bokeh/numpy/pandas 제약은 유지한다. 검증: pytest tests/unit 141 passed, tests/integration 16 passed, POST /api/v1/backtest 200 OK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lockfile 갱신 (package.json range 내에서 해결):
- react-router-dom → 6.30.4 (XSS via Open Redirect)
- axios → 1.19.0 (SSRF NO_PROXY 우회, 프로토타입 오염 인증 우회)
- vite → 7.3.6 (Path Traversal, server.fs.deny 우회)
- postcss → 8.5.25 (XSS, 임의 파일 읽기)
- happy-dom → 20.11.1 (cross-origin 쿠키 유출)
- 전이 의존성: ws, lodash, minimatch, brace-expansion, form-data,
glob, rollup, tmp, js-yaml, yaml, picomatch, flatted, path-to-regexp
메이저 업그레이드 (3.x/6.x에 패치 없음):
- jspdf ^3.0.3 → ^4.2.1 (CRITICAL: LFI/Path Traversal, PDF Injection)
- vitest, @vitest/ui, @vitest/coverage-v8 ^3.2.4 → ^4.1.10
(CRITICAL: UI 서버 구동 시 임의 파일 읽기/실행)
- @typescript-eslint/{eslint-plugin,parser} ^6.0.0 → ^8.65.0
vitest 4 대응:
- vitest.config.ts: poolOptions.forks.singleFork 제거됨
→ maxWorkers: 1 + isolate: false 로 대체
- src/test/setup.ts: vi.fn() 화살표 함수는 new 호출 불가하므로
IntersectionObserver/ResizeObserver 목을 class로 변경.
happy-dom이 window.alert/confirm/prompt를 구현하지 않아
vi.spyOn 대상이 되도록 no-op 스텁 추가.
@typescript-eslint 8 대응:
- LatestNewsSection.tsx: 미사용 catch 파라미터 제거
npm audit: 38건(critical 4/high 26) → 11건(critical 0/high 9).
남은 9건은 모두 eslint 8에서 파생되며 eslint 10 메이저가 필요해
다음 단계로 미룬다.
검증: test:run 94 passed(기존 실패 4건 동일, 회귀 없음),
type-check 통과, build 성공. lint 실패 74건은 @typescript-eslint 6에서도
동일하게 재현되는 기존 문제로 이번 변경과 무관.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jspdf와 html2canvas는 소스 어디에서도 import되지 않는 죽은 의존성이다. (src/, e2e/, __tests__/ 전체에서 참조 0건 — package.json에만 존재) 직전 커밋에서 jspdf를 4.2.1로 올려 CRITICAL을 해소했지만, 애초에 사용하지 않으므로 제거하는 편이 낫다. 21개 패키지가 함께 정리된다. .gitignore에 .idea/ 와 .DS_Store 추가. 검증: test:run 94 passed(기존 실패 4건 동일), type-check 통과, build 성공. npm audit 11건 유지(critical 0). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- eslint ^8.45.0 → ^10.8.0 - eslint-plugin-react-hooks ^4.6.0 → ^7.1.1 - eslint-plugin-react-refresh ^0.4.3 → ^0.5.3 - package.json의 eslintConfig 블록 제거 → eslint.config.js 신규 작성 - flat config에는 --ext가 없으므로 lint/lint:fix 스크립트에서 제거하고 대상 지정은 config의 files 글롭으로 이관. dist/coverage 등은 ignores로 명시. react-hooks v7의 recommended 프리셋은 React Compiler 규칙 약 27개를 추가로 켜기 때문에 v4와 동등하지 않다. 규칙 동등성을 유지하려고 rules-of-hooks(error)와 exhaustive-deps(warn) 두 개만 명시적으로 지정했다. npm audit 11건(high 9, moderate 2) → 2건(moderate 2). high 9건은 전부 eslint 8 의존 트리의 brace-expansion GHSA-mh99-v99m-4gvg 하나에서 파생된 것으로 이번 업그레이드로 해소됐다. 남은 moderate 2건은 react-router로 6.x에 패치가 없어 7.x 업그레이드가 필요하다. 검증: lint 74 problems(67 errors, 7 warnings) — 마이그레이션 전과 정확히 동일. 검사 파일 156개, 규칙별 내역도 no-explicit-any 65 / exhaustive-deps 7 / prefer-const 2로 일치하여 flat config가 대상을 누락하지 않음을 확인했다. test:run 94 passed(기존 실패 4건 동일), type-check 통과, build 성공, dev 서버 200. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
6.x에는 패치가 없는 취약점을 해소한다: - Open redirect via backslash in <Link>/useNavigate (GHSA-wrjc-x8rr-h8h6) - Open redirect leading to XSS (react-router-dom) 취약 범위가 6.0.0 - 7.17.0 이라 7.18 이상이 유일한 해결책이다. 미사용 @types/react-router-dom(^5.3.3) 제거 — v6부터 자체 타입을 제공한다. 앱은 BrowserRouter/Routes/Route/Navigate/Link/useLocation만 사용하는 선언형 라우팅이라 v7 breaking change에 걸리는 부분이 없어 소스 수정은 없었다. 다만 단위 테스트가 라우팅을 거의 검증하지 않아, 라우트 매칭 / <Navigate> 리다이렉트 / <Link> 내비게이션을 확인하는 스모크 테스트를 추가했다. 주의 — npm audit은 2 moderate → 2 high로 숫자가 나빠 보이지만 내용이 다르다. 7.12.0 이상에 RSC 모드 CSRF 우회 권고가 새로 붙었는데, 이 앱은 RSC/프레임워크 모드를 쓰지 않는 클라이언트 SPA라 해당 경로를 타지 않는다. 반대로 해소된 open redirect는 <Link>/useNavigate를 통해 실제로 노출되던 문제다. 현재 react-router에는 두 권고를 모두 피하는 버전이 존재하지 않는다(7.11 이하는 open redirect, 7.12 이상은 RSC 권고). 실질 위험 기준으로 7.18.2가 낫다고 판단했다. 검증: test:run 99 passed(신규 라우팅 5건 포함, 기존 실패 4건 동일), lint 74 problems 동일, type-check 통과, build 성공, dev 서버 200. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
compose.dev.yaml로 스택을 띄우려면 저장소 루트에 .env가 필요한데 해당 샘플이 없어 처음부터 재현이 불가능했다. 두 가지 문제가 있었다. 1. mysql 서비스에 MYSQL_ROOT_PASSWORD가 없어 컨테이너가 기동하지 않고, MYSQL_USER/MYSQL_PASSWORD도 없어 DATABASE_USER로 지정한 계정이 생성되지 않았다. → environment에 기본값과 함께 추가. .env에 MYSQL_* 키가 없어도 로컬 개발 기본값으로 동작한다. (.env 파일 자체는 env_file 지시자 때문에 여전히 필수) 2. 루트 .env.example 신규 작성. 기존 backtest_be_fast/.env.example은 네이티브 실행용이라 Docker에 필요한 MYSQL_*, VITE_API_BASE_URL, API_PROXY_TARGET, FASTAPI_PROXY_TARGET 키가 없었다. DATABASE_HOST가 localhost가 아닌 서비스명 mysql이어야 한다는 점, 프록시 대상이 backtest-be-fast여야 한다는 점을 주석으로 명시했다. backtest_be_fast/.env.example에는 앱이 실제로 읽는 백테스팅 설정 키를 보완하고, Docker 실행 시 루트 샘플을 쓰라는 안내를 추가했다. README의 Docker 실행 절차에도 cp .env.example .env 단계를 넣었다. 검증: .env에서 MYSQL_* 를 제거한 상태로 docker compose config 실행 시 기본값으로 해석되는 것을 확인했고, 동일한 환경변수 조합으로 mysql:8.0을 격리 기동해 appuser 접속과 schema.sql 적재(daily_prices, stock_news, stocks)까지 확인했다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
의존성 점검 결과를 반영해 FE/BE의 주요 패키지를 업그레이드하고, 로컬 Docker 개발 환경에서 필요한 환경변수 설정을 문서화하여 npm audit 취약점을 크게 줄이려는 PR입니다. 백테스트 플랫폼의 런타임/테스트/린트 도구체인을 최신화하면서도(특히 FE의 vitest/eslint/react-router, BE의 fastapi/pydantic/yfinance) 기존 제약(backtesting==0.3.3 등)은 유지합니다.
Changes:
- FE: react-router-dom v7 업그레이드에 맞춰 라우팅 스모크 테스트 추가, Vitest 4 설정/해피돔 스텁 보강, ESLint 10 flat config로 마이그레이션
- BE: FastAPI/Pydantic 및 yfinance(1.5.2) 등 핵심 의존성 업그레이드
- Infra/Docs: compose.dev.yaml의 MySQL 기본 env 보강 및 루트
.env.example/README로 로컬 Docker 실행 절차 문서화
Reviewed changes
Copilot reviewed 11 out of 13 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Docker 실행 시 루트 .env 준비 절차를 명시해 로컬 실행 가이드 보강 |
| compose.dev.yaml | MySQL 컨테이너가 .env 일부 키 누락 시에도 기동 가능하도록 기본값 추가 |
| backtest_fe/vitest.config.ts | Vitest 4 변경사항 반영(poolOptions 제거) 및 단일 워커/비격리 실행 설정 |
| backtest_fe/src/test/setup.ts | happy-dom 환경에서 alert/confirm/prompt 및 Observer 모킹을 Vitest 4에 맞게 보강 |
| backtest_fe/src/features/backtest/components/results/LatestNewsSection.tsx | 불필요한 catch (error) 바인딩 제거로 코드 정리 |
| backtest_fe/src/tests/routing.test.tsx | react-router-dom v7 마이그레이션 안전장치로 라우팅 스모크 테스트 신규 추가 |
| backtest_fe/package.json | FE 의존성 업그레이드(react-router-dom/vitest/eslint/@typescript-eslint 등) 및 미사용 패키지 제거 |
| backtest_fe/eslint.config.js | ESLint 10 flat config 도입 및 기존 규칙 동등성 유지(react-hooks는 명시 규칙) |
| backtest_be_fast/requirements.txt | BE 의존성 업그레이드(FastAPI/Pydantic/yfinance 등), backtesting==0.3.3 핀 유지 |
| backtest_be_fast/.env.example | 도커/네이티브 환경변수 샘플 사용처를 명확히 하는 주석 보강 |
| .gitignore | IDE(macOS/IntelliJ) 산출물 무시 규칙 추가 |
| .env.example | compose.dev.yaml 구동을 위한 루트 .env 샘플 신규 추가 |
This was referenced Jul 31, 2026
kyj0503
added a commit
that referenced
this pull request
Aug 2, 2026
#47·#48·#49로 스택과 검증 체계가 바뀌었는데 문서가 따라가지 못했다. 실측한 값으로만 갱신했고, 문서에 적은 명령·경로·수치는 모두 실행해 존재를 확인했다. ## 사실과 달랐던 것 - backtest_fe/README.md: React 18 표기(실제 19), 테스트 13파일/98건 (실제 16/113), 커버리지 17.13%(실제 21.81%), 존재하지 않는 src/components/ 디렉터리 설명, shared 파일 수 불일치, 끊긴 링크 4개(TEST.md 등 모두 부재) - backtest_fe/docs/testing/execution.md: 설정 파일을 vite.config.ts로 안내(실제 vitest.config.ts), 환경을 jsdom으로 안내(실제 happy-dom) - backtest_be_fast/tests/README.md: 총 68건(실제 141건) - UNIT_TEST_QUICK_REFERENCE.md: 파일별 개수 3건 불일치, 하드코딩된 타인 절대경로(/home/coontec/...), venv 기반 실행 안내, 실제와 다른 CI 예시(GitHub Actions/venv) - TEST_COVERAGE_SUMMARY.md: 파일별 개수 3건 불일치, venv 실행 안내 (합계 59건은 이 문서가 다루는 4개 모듈 기준으로 지금도 정확해 유지) - README.md(루트): backtest_fe/__tests__/ 구조(이제 src 안으로 이동), 스택 버전 미표기 ## 새로 담은 것 - CI Quality Gate의 존재와 재현 방법(docker build --target test) - 게이트가 배포는 막지만 병합은 막지 않는다는 점(브랜치 보호 미사용) - type-check와 type-check:test의 분리 이유 - lint 경고 상한 3이 래칫이라는 점과 목표 - Tailwind 4 제약(설정이 index.css, @theme에 색상 리터럴 금지, .app-container) - vitest isolate:false 금지 이유 - FE build의 NODE_ENV=production 고정 이유 - VITE_API_BASE_URL을 비워야 하는 계약 - build:analyze가 현재 실질적으로 build와 동일하다는 주의 CLAUDE.md와 .github/copilot-instructions.md에는 위 제약들을 에이전트가 반복해서 밟지 않도록 명시했다. BE 문서 2건은 편집 과정에서 CRLF가 LF로 바뀌어 원래 개행으로 되돌렸다. 코드 변경은 없다(마크다운만). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
개요
의존성 점검 결과에 따라 보안 취약점을 해소하고 오래된 패키지를 정리했습니다.
npm audit38건(critical 4 / high 26) → 2건, BE는yfinance를 1.x로 올렸습니다.모든 검증은
compose.dev.yaml컨테이너 안에서 실행했습니다.커밋
chore(be)fix(fe)chore(fe)chore(fe)fix(fe)chore(infra)판단이 필요했던 지점
1. yfinance 0.2 → 1.x 에서 백테스트 수치가 바뀌는가 → 아니오
가장 큰 리스크는 1.x에서 바뀐
auto_adjust기본값이었습니다. 호출부(
app/utils/data_fetcher.py:121,123)가auto_adjust=True를 명시적으로전달하고 있어 영향을 받지 않습니다.
실측으로 확인했습니다. 컨테이너에서 yfinance를 0.2.65로 되돌려 동일 구간
(AAPL, 005930.KS / 2023-01-01~06-30) 종가를 대조:
2. react-router 7 업그레이드로 audit 숫자가 나빠 보임 → 실질 위험은 개선
2 moderate → 2 high로 숫자만 보면 악화지만 내용이 다릅니다.<Link>/useNavigate(+ XSS 연계).이 앱은
<Link>와 클라이언트 라우팅을 쓰므로 실제 노출되던 경로7.12.0 - 8.2.0). 이 앱은BrowserRouter선언형 SPA로
createBrowserRouter도 RSC/프레임워크 모드도 쓰지 않음 (참조 0건 확인).타지 않는 경로
두 권고를 모두 피하는 버전은 현재 존재하지 않습니다 (7.11 이하는 open redirect,
7.12 이상은 RSC 권고, 7.18.2가 최신). npm이 제안하는 "fix"인 7.11.0은
open redirect를 되살리는 다운그레이드입니다. 실질 위험 기준으로 7.18.2를 택했습니다.
3. eslint-plugin-react-hooks v7 의 recommended 프리셋은 v4와 동등하지 않음
v7 프리셋은 React Compiler 규칙 약 27개를 추가로 켭니다. 그대로 썼다면 lint 결과가
크게 달라졌을 것이라,
rules-of-hooks(error)와exhaustive-deps(warn) 두 개만명시해 규칙 동등성을 유지했습니다. React Compiler 도입은 별도 판단 사안이라 제외했습니다.
유지한 제약
backtesting==0.3.3핀과 그에 묶인bokeh 2.4.3/numpy<2/pandas<3는그대로 뒀습니다 (CLAUDE.md 제약 2번). 0.6.6은 결과 수치가 달라지므로 회귀 검증이
선행되어야 합니다.
React 18→19, recharts 2→3, tailwindcss 3→4 도 범위에서 제외했습니다.
보안 사유가 없고 대시보드 UI 전반의 회귀 확인이 필요합니다.
검증
pytest tests/unitpytest tests/integrationPOST /api/v1/backtestnpm run test:runnpm run type-checknpm run buildnpm audit알려진 이슈 (이 PR 범위 밖)
portfolioCalculations.test.ts3건,ThemeSelector.test.tsx1건입니다.회귀가 아니며 순증 0입니다.
npm run lint가 74건(67 errors, 7 warnings)으로 실패합니다.기존
no-explicit-any위반이며, eslint 6 / 8 / 10 세 조건에서 동일하게측정되어 이번 변경과 무관함을 확인했습니다. 별도 정리 과제입니다.
라우팅 검증은 추가한 스모크 테스트(5건)로 대체했습니다.
🤖 Generated with Claude Code