Skip to content

Latest commit

ย 

History

28 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ai-cve-watch โ€” AI ์˜คํ”ˆ์†Œ์Šค CVE ์ž๋™ ์ˆ˜์ง‘๊ธฐ

์ธํ„ฐ๋„ท๋ง์—์„œ ํ•˜๋ฃจ 1ํšŒ ์ž๋™ ์‹คํ–‰๋˜์–ด AI ์˜คํ”ˆ์†Œ์Šค(PyTorchยทvLLMยทLangChain ๋“ฑ 55์ข…)์˜ ์‹ ๊ทœ CVE๋ฅผ ์ˆ˜์ง‘ โ†’ ์—‘์…€(CVE_YYYYMMDD.xls) ์ƒ์„ฑ โ†’ ๋ฉ”์ผ ๋ฐœ์†ก โ†’ DB ์ ์žฌ โ†’ ์›น ํŽ˜์ด์ง€ ์—ด๋žŒ๊นŒ์ง€ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ „๋ถ€ ๋ฌด๋ฃŒ ์„œ๋น„์Šค๋งŒ ์”๋‹ˆ๋‹ค(์‹ ์šฉ์นด๋“œ ๋ถˆํ•„์š”).

์ƒ์„ฑ๋œ ์—‘์…€์€ ํ์‡„๋ง(๋‚ด๋ถ€๋ง) SW๊ด€๋ฆฌ๋„๊ตฌ๋กœ ๋ฐ˜์ž…๋˜์–ด ๊ทธ๋Œ€๋กœ ํŒŒ์‹ฑ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ 5. ์—‘์…€ ์ถœ๋ ฅ ๊ทœ๊ฒฉ์€ ํ•œ ๊ธ€์ž๋„ ๋ฐ”๊พธ๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

GitHub Actions (๋งค์ผ 06:00 KST)
   โ””โ”€ ์ˆ˜์ง‘ NVDยทOSVยทGHSAยทKEV
        โ””โ”€ ๋ณ‘ํ•ฉยท์ •๊ทœํ™” (๋ฒ„์ „๋ฒ”์œ„ ๋ฌธ์ž์—ด ๋ณ€ํ™˜)
             โ”œโ”€ output/CVE_YYYYMMDD.xls   โ† ๋‚ด๋ถ€๋ง ๋ฐ˜์ž…์šฉ ์ •๋ณธ
             โ”œโ”€ ๋ฉ”์ผ ๋ฐœ์†ก (๊ฐœ๋ณ„ ๋ฐœ์†ก)
             โ”œโ”€ data/cve.db (SQLite, ์ €์žฅ์†Œ์— ์ปค๋ฐ‹)
             โ””โ”€ docs/ (GitHub Pages ์—ด๋žŒ ํŽ˜์ด์ง€)

๋ชฉ์ฐจ

  1. 5๋ถ„ ์…‹์—…
  2. ๊ฐ์‹œ ๋Œ€์ƒ(watchlist) ์ถ”๊ฐ€ํ•˜๊ธฐ
  3. Gmail ์•ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ฐœ๊ธ‰
  4. 60์ผ ์ž๋™ ๋น„ํ™œ์„ฑํ™” ๋Œ€์‘
  5. ์—‘์…€ ์ถœ๋ ฅ ๊ทœ๊ฒฉ (๋‚ด๋ถ€๋ง ๋‹ด๋‹น์ž ์ „๋‹ฌ์šฉ)
  6. ๋ฌด๋ฃŒ ํ‹ฐ์–ด ํ•œ๊ณ„์™€ Supabase ์ „ํ™˜
  7. ์ˆ˜์ง‘ ๋ฒ”์œ„(Scope) ์กฐ์ ˆํ•˜๊ธฐ
  8. CLI ์‚ฌ์šฉ๋ฒ•
  9. ์ €์žฅ์†Œ ๊ตฌ์กฐ
  10. ๋ฌธ์ œ ํ•ด๊ฒฐ
  11. SUMMARY ํ•œ๊ตญ์–ด ๋ฒˆ์—ญ

1. 5๋ถ„ ์…‹์—…

์ˆœ์„œ๋ฅผ ์ง€์ผœ ์ฃผ์„ธ์š”. โ‘ โ‘กโ‘ขโ‘ฃ ๋ฅผ ๋งˆ์ณ ์ €์žฅ์†Œ์— ํŒŒ์ผ์ด ์˜ฌ๋ผ๊ฐ€๊ณ  docs/ ๊ฐ€ ๋งŒ๋“ค์–ด์ง„ ๋’ค์—์•ผ โ‘ค GitHub Pages ์„ค์ •์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋น„์–ด ์žˆ๋Š” ์ €์žฅ์†Œ์—์„œ Settings โ†’ Pages ๋กœ ๋จผ์ € ๊ฐ€๋ฉด "You must first add content to your repository" ๋งŒ ๋œจ๊ณ  Branch ๋“œ๋กญ๋‹ค์šด์ด None ํ•˜๋‚˜๋ฟ์ด๋ผ /docs ๋ฅผ ๊ณ ๋ฅผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

โ‘  ์ €์žฅ์†Œ ์ค€๋น„ + ์ฝ”๋“œ ์˜ฌ๋ฆฌ๊ธฐ (1๋ถ„)

์ด ์ €์žฅ์†Œ๋ฅผ Public ์œผ๋กœ ํฌํฌํ•˜๊ฑฐ๋‚˜, ์ƒˆ๋กœ ๋งŒ๋“  ๋’ค ์ด ํด๋”์˜ ๋‚ด์šฉ์„ push ํ•ฉ๋‹ˆ๋‹ค.

git init
git add .
git commit -m "init: ai-cve-watch"
git branch -M main
git remote add origin https://github.com/<์‚ฌ์šฉ์ž๋ช…>/<์ €์žฅ์†Œ๋ช…>.git
git push -u origin main

Public ์ด์–ด์•ผ GitHub Actions ๊ฐ€ ๋ฌด์ œํ•œ ๋ฌด๋ฃŒ์ž…๋‹ˆ๋‹ค. Private ์€ ์›” 2,000๋ถ„ ์ œํ•œ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

โ‘ก Secrets ๋“ฑ๋ก (2๋ถ„)

์ €์žฅ์†Œ โ†’ Settings โ†’ Secrets and variables โ†’ Actions โ†’ New repository secret

์ด๋ฆ„ ํ•„์ˆ˜ ๊ฐ’ ์„ค๋ช…
SMTP_HOST โœ… smtp.gmail.com ๋„ค์ด๋ฒ„๋Š” smtp.naver.com
SMTP_PORT โœ… 587 SSL ์„ ์“ฐ๋ ค๋ฉด 465
SMTP_USER โœ… your@gmail.com ๋ณด๋‚ด๋Š” ๊ณ„์ •
SMTP_PASS โœ… ์•ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ 16์ž๋ฆฌ ๊ณ„์ • ๋น„๋ฐ€๋ฒˆํ˜ธ ์•„๋‹˜ โ†’ 3์žฅ
MAIL_FROM โœ… AI CVE Watch <your@gmail.com> ๋ณด๋‚ด๋Š” ์‚ฌ๋žŒ ํ‘œ์‹œ
NVD_API_KEY โฌœ NVD ๋ฐœ๊ธ‰ ํ‚ค ์—†์–ด๋„ ๋™์ž‘(์š”์ฒญ ๊ฐ„ 6.5์ดˆ ๋Œ€๊ธฐ). ์žˆ์œผ๋ฉด 0.7์ดˆ๋กœ ๋‹จ์ถ•
GITHUB_TOKEN โ€” ์ž๋™ Actions ๊ฐ€ ์ž๋™ ์ฃผ์ž…. ์ง์ ‘ ๋“ฑ๋ก ๋ถˆํ•„์š”

NVD_API_KEY ๋Š” https://nvd.nist.gov/developers/request-an-api-key ์—์„œ ๋ฌด๋ฃŒ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค. 55์ข…์„ ๋งค์ผ ๋„๋Š” ๋ฐ ํ‚ค๊ฐ€ ์—†์œผ๋ฉด ์•ฝ 6๋ถ„, ์žˆ์œผ๋ฉด ์•ฝ 1๋ถ„ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. ๋„ฃ๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

โ‘ข ์ˆ˜์‹ ์ž ๋“ฑ๋ก (30์ดˆ)

mail_list.txt ๋ฅผ ์—ด์–ด ๋ฐ›์„ ์‚ฌ๋žŒ์˜ ์ฃผ์†Œ๋ฅผ 1์ค„์— 1๊ฐœ์”ฉ ์ ์Šต๋‹ˆ๋‹ค.

security-team@example.com
sbom-admin@example.com
# ์•ž์— #์„ ๋ถ™์ด๋ฉด ์ž ์‹œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค

โ‘ฃ ์ˆ˜๋™์œผ๋กœ 1ํšŒ ์‹คํ–‰ (30์ดˆ + ๋Œ€๊ธฐ)

์ €์žฅ์†Œ โ†’ Actions โ†’ daily-cve-collect โ†’ Run workflow

  • ์ฒซ ์‹คํ–‰์€ preset ์„ backfill ๋กœ ๋‘๋ฉด ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ๊นŒ์ง€ ์ฑ„์›๋‹ˆ๋‹ค(์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค).
  • ๊ฐ€๋ณ๊ฒŒ ํ™•์ธ๋งŒ ํ•˜๋ ค๋ฉด preset = urgent, sources = osv,kev ๋กœ ๋‘์„ธ์š” (2~3๋ถ„).

์‹คํ–‰์ด ๋๋‚˜๋ฉด output/CVE_YYYYMMDD.xls ๊ฐ€ ์ปค๋ฐ‹๋˜๊ณ , ๋ฉ”์ผ์ด ๋ฐœ์†ก๋˜๊ณ , docs/ ํด๋”๊ฐ€ ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. Code ํƒญ์—์„œ docs ํด๋”๊ฐ€ ๋ณด์ด๋Š”์ง€ ํ™•์ธํ•œ ๋’ค โ‘ค๋กœ ๋„˜์–ด๊ฐ€์„ธ์š”.

Actions ํƒญ์—์„œ "Workflows aren't being run on this forked repository" ๋ฐฐ๋„ˆ๊ฐ€ ๋ณด์ด๋ฉด I understand my workflows, go ahead and enable them ์„ ๋ˆŒ๋Ÿฌ ์ฃผ์„ธ์š”(ํฌํฌํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋‚˜์˜ต๋‹ˆ๋‹ค).

โ‘ค GitHub Pages ์ผœ๊ธฐ (1๋ถ„)

์ €์žฅ์†Œ โ†’ Settings โ†’ Pages ๋กœ ์ด๋™ํ•ด์„œ

ํ•ญ๋ชฉ ์„ ํƒํ•  ๊ฐ’
Source Deploy from a branch
Branch main โ† โ‘ฃ๋ฅผ ๋งˆ์ณ์•ผ ๋ชฉ๋ก์— ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค
Folder /docs โ† โ˜… ๋ฃจํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ docs ์ž…๋‹ˆ๋‹ค. ๋ธŒ๋žœ์น˜๋ฅผ ๊ณ ๋ฅด๋ฉด ์˜ค๋ฅธ์ชฝ์— ์ƒ๊น๋‹ˆ๋‹ค

Save ๋ฅผ ๋ˆ„๋ฅด๋ฉด 1~2๋ถ„ ๋’ค https://<์‚ฌ์šฉ์ž๋ช…>.github.io/<์ €์žฅ์†Œ๋ช…> ์—์„œ ์—ด๋žŒ ํŽ˜์ด์ง€๊ฐ€ ์—ด๋ฆฝ๋‹ˆ๋‹ค.

Branch ๋ชฉ๋ก์— main ์ด ์—†๊ณ  None ๋ฟ์ด๋ผ๋ฉด ์•„์ง ์ €์žฅ์†Œ์— ์ฝ”๋“œ๊ฐ€ ์•ˆ ์˜ฌ๋ผ๊ฐ„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. โ‘ ์˜ push ๊ฐ€ ๋๋‚ฌ๋Š”์ง€, Code ํƒญ์— ํŒŒ์ผ์ด ๋ณด์ด๋Š”์ง€ ๋จผ์ € ํ™•์ธํ•˜์„ธ์š”. ํด๋” ๋“œ๋กญ๋‹ค์šด(/ (root), /docs)์€ ๋ธŒ๋žœ์น˜๋ฅผ ๋จผ์ € ์„ ํƒํ•ด์•ผ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.


2. ๊ฐ์‹œ ๋Œ€์ƒ(watchlist) ์ถ”๊ฐ€ํ•˜๊ธฐ

config/watchlist.yml ์— ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

- canonical_name: PyTorch          # โ˜… ๋‚ด๋ถ€๋ง TB_SW.SW_NM ๊ณผ ๋ฐ˜๋“œ์‹œ ์ผ์น˜์‹œํ‚ฌ ๊ฒƒ
  aliases: [torch, pytorch, "pytorch/pytorch"]
  ecosystem: pypi                  # pypi / npm / github / other
  pypi: torch                      # OSV ์กฐํšŒ์šฉ (npm: / go: ๋„ ๊ฐ€๋Šฅ)
  github: pytorch/pytorch          # GHSA ์กฐํšŒยท์ฐธ๊ณ  URL์šฉ
  cpe_keyword: pytorch             # NVD keywordSearch ๊ฒ€์ƒ‰์–ด
  vendor: PyTorch Foundation       # ์—‘์…€ VENDOR ์ปฌ๋Ÿผ ๊ธฐ๋ณธ๊ฐ’
  group: framework                 # framework/serving/library/app/ui/vectordb/mlops/base
  enabled: true                    # false ๋ฉด ์ˆ˜์ง‘ ๋Œ€์ƒ์—์„œ ์™„์ „ ์ œ์™ธ
  in_use: true                     # ๋‚ด๋ถ€๋ง์— ์‹ค์ œ ๋ฐ˜์ž…๋œ S/W ์ธ์ง€

โš ๏ธ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ฃผ์˜์‚ฌํ•ญ

canonical_name ์€ ๋‚ด๋ถ€๋ง TB_SW.SW_NM ๊ฐ’๊ณผ ๊ธ€์ž ํ•˜๋‚˜๊นŒ์ง€ ๋˜‘๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—‘์…€ SW_NAME ์ปฌ๋Ÿผ์—๋Š” ์›๋ณธ ํŒจํ‚ค์ง€๋ช…(torch)์ด ์•„๋‹ˆ๋ผ ์ด canonical_name(PyTorch)์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ๋‚ด๋ถ€๋ง ๊ด€๋ฆฌ๋„๊ตฌ๋Š” ์ด ๊ฐ’์œผ๋กœ ์ž์‚ฐ์„ ๋งค์นญํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋‚ด๋ถ€๋ง์— PyTorch ๋กœ ๋“ฑ๋ก๋ผ ์žˆ๋Š”๋ฐ ์—ฌ๊ธฐ์— Pytorch ๋‚˜ torch ๋กœ ์ ์œผ๋ฉด ์ทจ์•ฝ์ ์ด ์–ด๋А ์ž์‚ฐ์—๋„ ๋ถ™์ง€ ์•Š๊ณ  ๊ทธ๋ƒฅ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์ƒˆ S/W ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋Š” ๋จผ์ € ๋‚ด๋ถ€๋ง ๋ชฉ๋ก์—์„œ ์ •ํ™•ํ•œ ์ด๋ฆ„์„ ํ™•์ธํ•œ ๋’ค ๊ทธ๋Œ€๋กœ ์˜ฎ๊ฒจ ์ ์œผ์„ธ์š”.

์ถ”๊ฐ€ ํ›„ ํ™•์ธ:

python -m src.aicve.main --show-scope --sw-names "์ƒˆ๋กœ์ถ”๊ฐ€ํ•œ์ด๋ฆ„"
# ๋Œ€์ƒ S/W 1์ข…: ์ƒˆ๋กœ์ถ”๊ฐ€ํ•œ์ด๋ฆ„   โ† ์ด๋ ‡๊ฒŒ ๋‚˜์˜ค๋ฉด ์ •์ƒ

in_use ๋ฅผ ์ •ํ™•ํžˆ ๊ด€๋ฆฌํ•ด ๋‘๋ฉด --only-in-use ๋กœ ์‹ค์ œ ๋ฐ˜์ž…ํ•œ S/W ๋งŒ ์ขํ˜€ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


3. Gmail ์•ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ฐœ๊ธ‰

Gmail ์€ 2023๋…„๋ถ€ํ„ฐ ์ผ๋ฐ˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ SMTP ๋กœ๊ทธ์ธ์ด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ์•ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  1. 2๋‹จ๊ณ„ ์ธ์ฆ์„ ๋จผ์ € ์ผญ๋‹ˆ๋‹ค โ†’ https://myaccount.google.com/security โ†’ 2๋‹จ๊ณ„ ์ธ์ฆ โ†’ ์•ˆ๋‚ด์— ๋”ฐ๋ผ ์„ค์ • (์•ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 2๋‹จ๊ณ„ ์ธ์ฆ์ด ์ผœ์ ธ ์žˆ์–ด์•ผ ๋‚˜์˜ต๋‹ˆ๋‹ค)
  2. https://myaccount.google.com/apppasswords ์ ‘์†
  3. ์•ฑ ์ด๋ฆ„์— ai-cve-watch ์ž…๋ ฅ โ†’ ๋งŒ๋“ค๊ธฐ
  4. abcd efgh ijkl mnop ํ˜•ํƒœ์˜ 16์ž๋ฆฌ๊ฐ€ ๋œน๋‹ˆ๋‹ค โ†’ ๊ณต๋ฐฑ์„ ๋นผ๊ณ  abcdefghijklmnop ๋กœ ๋ณต์‚ฌ
  5. GitHub Secrets ์˜ SMTP_PASS ์— ๋ถ™์—ฌ๋„ฃ๊ธฐ (์ด ํ™”๋ฉด์„ ๋‹ซ์œผ๋ฉด ๋‹ค์‹œ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค)

๋„ค์ด๋ฒ„ ๋ฉ”์ผ์„ ์“ด๋‹ค๋ฉด: ๋„ค์ด๋ฒ„ ๋ฉ”์ผ โ†’ ํ™˜๊ฒฝ์„ค์ • โ†’ POP3/IMAP ์„ค์ • โ†’ IMAP/SMTP ์‚ฌ์šฉํ•จ, ๊ทธ๋ฆฌ๊ณ  SMTP_HOST=smtp.naver.com, SMTP_PORT=587, SMTP_USER ๋Š” ์•„์ด๋””(@naver.com ํฌํ•จ).


4. 60์ผ ์ž๋™ ๋น„ํ™œ์„ฑํ™” ๋Œ€์‘

GitHub ๊ทœ์น™: Public ์ €์žฅ์†Œ์˜ schedule ์›Œํฌํ”Œ๋กœ๋Š” 60์ผ๊ฐ„ ์ €์žฅ์†Œ์— ํ™œ๋™(์ปค๋ฐ‹)์ด ์—†์œผ๋ฉด ์ž๋™์œผ๋กœ ๋น„ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค.

์ด ์ €์žฅ์†Œ๋Š” ๋Œ€๊ฐœ ๋ฌธ์ œ์—†์Šต๋‹ˆ๋‹ค. ๋งค์ผ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค data/cve.dbยทoutput/ยทdocs/ ๋ฅผ ์ž๋™ ์ปค๋ฐ‹ํ•˜๋ฏ€๋กœ ํ™œ๋™์ด ๊ณ„์† ๊ธฐ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‹ค๋งŒ ์•„๋ž˜ ๊ฒฝ์šฐ์—๋Š” ๋ฉˆ์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์˜ค๋žซ๋™์•ˆ ์‹ ๊ทœ CVE๊ฐ€ 0๊ฑด์ด๋ผ ์ปค๋ฐ‹ํ•  ๋ณ€๊ฒฝ์ด ์—†์—ˆ๋˜ ๊ฒฝ์šฐ
  • ์›Œํฌํ”Œ๋กœ๊ฐ€ ๊ณ„์† ์‹คํŒจํ•ด์„œ ์ปค๋ฐ‹ ๋‹จ๊ณ„๊นŒ์ง€ ๋ชป ๊ฐ”๋˜ ๊ฒฝ์šฐ

๋น„ํ™œ์„ฑํ™”๋˜๋ฉด ์ด๋ ‡๊ฒŒ ๋˜์‚ด๋ฆฝ๋‹ˆ๋‹ค

  1. ์ €์žฅ์†Œ โ†’ Actions ํƒญ โ†’ ๋…ธ๋ž€ ๋ฐฐ๋„ˆ "This scheduled workflow is disabled because there hasn't been activity in this repository for 60 days"
  2. ๋ฐฐ๋„ˆ์˜ Enable workflow ๋ฒ„ํŠผ ํด๋ฆญ โ†’ ์ฆ‰์‹œ ์žฌ๊ฐœ๋ฉ๋‹ˆ๋‹ค.
  3. ๋ฐฐ๋„ˆ๊ฐ€ ์—†๋‹ค๋ฉด ์™ผ์ชฝ ๋ชฉ๋ก์—์„œ daily-cve-collect ์„ ํƒ โ†’ ์˜ค๋ฅธ์ชฝ Enable workflow

์˜ˆ๋ฐฉ์ฑ…

  • ์›Œํฌํ”Œ๋กœ์— workflow_dispatch(์ˆ˜๋™ ์‹คํ–‰) ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์ด๋ฏธ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๋‹ฌ์— ํ•œ ๋ฒˆ์ฏค Run workflow ๋ฅผ ๋ˆŒ๋Ÿฌ ์ฃผ๊ธฐ๋งŒ ํ•ด๋„ ํ™œ๋™์œผ๋กœ ์ธ์ •๋ฉ๋‹ˆ๋‹ค.
  • ์•Œ๋ฆผ์„ ๋ฐ›์œผ๋ ค๋ฉด: ์ €์žฅ์†Œ โ†’ Watch โ†’ Custom โ†’ Actions ์ฒดํฌ (์›Œํฌํ”Œ๋กœ ์‹คํŒจ ์‹œ ๋ฉ”์ผ์ด ์˜ต๋‹ˆ๋‹ค. ์ข…๋ฃŒ ์ฝ”๋“œ 1 ๋กœ ์‹คํŒจ๋ฅผ ์•Œ๋ฆฌ๋„๋ก ๋งŒ๋“ค์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.)

5. ์—‘์…€ ์ถœ๋ ฅ ๊ทœ๊ฒฉ (๋‚ด๋ถ€๋ง ๋‹ด๋‹น์ž ์ „๋‹ฌ์šฉ)

์ด ์žฅ์„ ๋‚ด๋ถ€๋ง ๊ด€๋ฆฌ๋„๊ตฌ ๋‹ด๋‹น์ž์—๊ฒŒ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•˜์„ธ์š”. ์ด ๊ทœ๊ฒฉ์€ ๊ณ ์ •์ด๋ฉฐ, ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ์–‘์ชฝ(์ˆ˜์ง‘๊ธฐยท๋‚ด๋ถ€๋ง ํŒŒ์„œ)์„ ๋™์‹œ์— ๊ณ ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํŒŒ์ผ

ํ•ญ๋ชฉ ๊ฐ’
ํŒŒ์ผ๋ช… CVE_YYYYMMDD.xls โ€” ๋ฐ˜๋“œ์‹œ ๋Œ€๋ฌธ์ž CVE_ ๋กœ ์‹œ์ž‘ (๋‚ด๋ถ€๋ง ๋„๊ตฌ๊ฐ€ ์ ‘๋‘์‚ฌ๋ฅผ ๊ฒ€์ฆ)
ํฌ๋งท BIFF8 .xls (xlwt ์ƒ์„ฑ) โ€” ์ด๊ฒƒ์ด ์ •๋ณธ
๋ถ€๊ฐ€ ํŒŒ์ผ ๊ฐ™์€ ๋‚ด์šฉ์˜ .xlsx(openpyxl), .csv(UTF-8 BOM). ๋ฐ˜์ž…์šฉ์€ ์–ด๋””๊นŒ์ง€๋‚˜ .xls
์‹œํŠธ1 CVE_LIST โ€” 1ํ–‰ ํ—ค๋”, 2ํ–‰๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ
์‹œํŠธ2 META โ€” KEY | VALUE 2์—ด

์‹œํŠธ1 CVE_LIST โ€” ํ—ค๋” 16๊ฐœ (์ˆœ์„œยท์ฒ ์ž ๊ณ ์ •)

# ํ—ค๋” ๊ฐ’ ๊ทœ์น™
1 CVE_ID CVE-YYYY-NNNN
2 SW_NAME watchlist ์˜ canonical_name (= ๋‚ด๋ถ€๋ง TB_SW.SW_NM)
3 VENDOR ์ œ์ž‘์‚ฌ/์กฐ์ง
4 AFFECTED_RANGE ์•„๋ž˜ ๋ฒ„์ „๋ฒ”์œ„ ๋ฌธ๋ฒ•, ๊ณต๋ฐฑ ์—†์Œ
5 FIXED_VERSION ์—†์œผ๋ฉด ๋นˆ ๋ฌธ์ž์—ด
6 SEVERITY CRITICAL / HIGH / MEDIUM / LOW / NONE
7 CVSS_SCORE 0.0~10.0, ๋ฌธ์ž์—ด ์…€
8 CVSS_VECTOR ์˜ˆ: CVSS:3.1/AV:N/AC:L/...
9 PUBLISHED_DATE YYYYMMDD ๋ฌธ์ž์—ด ์…€
10 MODIFIED_DATE YYYYMMDD ๋ฌธ์ž์—ด ์…€
11 KEV_YN Y / N (CISA ์‹ค์ œ ์•…์šฉ ํ™•์ธ ์—ฌ๋ถ€)
12 SUMMARY 1000์ž ์ด๋‚ด, ๊ฐœํ–‰ยทํƒญ์€ ๊ณต๋ฐฑ์œผ๋กœ ์น˜ํ™˜๋จ. ๊ธฐ๋ณธ๊ฐ’์€ ํ•œ๊ตญ์–ด ๋ฒˆ์—ญ๋ฌธ (11์žฅ)
13 REFERENCE_URL ๋Œ€ํ‘œ URL 1๊ฐœ
14 SOURCE NVD / OSV / GHSA (๋ณ‘ํ•ฉ ์‹œ NVD+OSV)
15 ECOSYSTEM pypi / npm / github / other
16 COLLECTED_AT YYYYMMDDHHmmss ๋ฌธ์ž์—ด ์…€

โ˜… ๋ชจ๋“  ์…€์€ ๋ฌธ์ž์—ด(text)์ž…๋‹ˆ๋‹ค

์ˆซ์žํ˜•์œผ๋กœ ์“ฐ๋ฉด ๋ฒ„์ „ 1.10 โ†’ 1.1, ๋‚ ์งœ โ†’ ์‹œ๋ฆฌ์–ผ๊ฐ’(45123)์œผ๋กœ ๊นจ์ ธ POI ํŒŒ์‹ฑ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ ์ˆ˜ยท๋‚ ์งœ๋ฅผ ํฌํ•จํ•œ ๋ชจ๋“  ์…€์„ ๋ฌธ์ž์—ด๋กœ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. None/NaN ์€ ๋นˆ ๋ฌธ์ž์—ด("")์ž…๋‹ˆ๋‹ค. ์ฝ๋Š” ์ชฝ์—์„œ๋„ ๋ฌธ์ž์—ด๋กœ ๋ฐ›์•„ ์ฃผ์„ธ์š”.

๋ฒ„์ „๋ฒ”์œ„(AFFECTED_RANGE) ๋ฌธ๋ฒ•

 ,  = AND        |  = OR        ์—ฐ์‚ฐ์ž: >= > <= < ==        ์ „์ฒด ์˜ํ–ฅ = *

 ">=1.0.0,<1.4.2"                 1.0.0 ์ด์ƒ 1.4.2 ๋ฏธ๋งŒ
 ">=2.0.0,<2.3.1|>=3.0.0,<3.0.4"  ๋‘ ๊ตฌ๊ฐ„ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ํ•ด๋‹น๋˜๋ฉด ์ทจ์•ฝ
 "==1.2.3"                        ์ •ํ™•ํžˆ ๊ทธ ๋ฒ„์ „๋งŒ
 "<2.6.0"                         2.6.0 ๋ฏธ๋งŒ ์ „๋ถ€ (ํ•˜ํ•œ์ด 0์ด๋ฉด ์ƒ๋žต)
 "*"                              ์ „ ๋ฒ„์ „ ์˜ํ–ฅ ๋˜๋Š” ๋ฒ”์œ„ ๋ถˆ๋ช…
  • ๋ฌธ์ž์—ด์— ๊ณต๋ฐฑ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ธธ์ด๊ฐ€ 500์ž๋ฅผ ๋„˜์œผ๋ฉด ๋Œ€ํ‘œ ๋ฒ”์œ„๋งŒ ๋‚จ๊ธฐ๊ณ  ์ž๋ฆ…๋‹ˆ๋‹ค.
  • ๋ฒ”์œ„๋ฅผ ์•Œ์•„๋‚ผ ์ˆ˜ ์—†์œผ๋ฉด * ๋กœ ์“ฐ๊ณ , SUMMARY ์•ž์— [๋ฒ„์ „๋ฒ”์œ„ ๋ถˆ๋ช…ํ™•] ์„ ๋ถ™์ž…๋‹ˆ๋‹ค. โ†’ ์ด ์ ‘๋‘์‚ฌ๊ฐ€ ๋ณด์ด๋ฉด ๋‹ด๋‹น์ž๊ฐ€ ์ˆ˜๋™ ํ™•์ธ์ด ํ•„์š”ํ•˜๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

์ •๋ ฌ

SEVERITY(CRITICALโ†’NONE) โ†’ CVSS_SCORE ๋‚ด๋ฆผ์ฐจ์ˆœ โ†’ SW_NAME โ†’ CVE_ID

์‹œํŠธ2 META ํ‚ค (์ˆ˜์ง‘ ์กฐ๊ฑด ์ถ”์ ์šฉ)

RUN_ID, COLLECTED_AT, SCOPE_DESC, DATE_FROM, DATE_TO, MIN_SEVERITY, GROUPS, SW_NAMES, ONLY_IN_USE, SOURCES, EXCEL_SCOPE, MAX_ROWS, TRUNCATED_CNT, TOTAL_CNT, NEW_CNT, UPDATED_CNT, TOOL_VERSION

  • SCOPE_DESC ์— ์ด ํŒŒ์ผ์ด ์–ด๋–ค ์กฐ๊ฑด์œผ๋กœ ๋ฝ‘ํ˜”๋Š”์ง€ ํ•œ ์ค„๋กœ ๋“ค์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: SCOPE lookback=3 sev>=MEDIUM groups=all sw=- in_use=False src=nvd,osv,ghsa,kev scope=delta max=300
  • TRUNCATED_CNT ๊ฐ€ 0๋ณด๋‹ค ํฌ๋ฉด ์ตœ๋Œ€ ํ–‰์ˆ˜ ์ œํ•œ์œผ๋กœ ์ž˜๋ ค ๋‚˜๊ฐ„ ๊ฑด์ด ์žˆ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์ „์ฒด ๋ชฉ๋ก์€ GitHub Pages ์—ด๋žŒ ํŽ˜์ด์ง€์—์„œ ํ™•์ธํ•˜์„ธ์š”.

ํ–‰ ์ˆ˜ ์ œํ•œ

xlwt(BIFF8)๋Š” ์‹œํŠธ๋‹น 65,536ํ–‰์ด ํ•œ๊ณ„๋ผ, ์ดˆ๊ณผ ์‹œ CVE_LIST, CVE_LIST_2, CVE_LIST_3 โ€ฆ ์œผ๋กœ ๋‚˜๋ˆ„๊ณ  META ์— SHEET_COUNTยทSHEET_NAMES ๋ฅผ ์ ์Šต๋‹ˆ๋‹ค. (๊ธฐ๋ณธ max_rows: 300 ์ด๋ผ ์‹ค์ œ๋กœ๋Š” ๊ฑฐ์˜ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)


6. ๋ฌด๋ฃŒ ํ‹ฐ์–ด ํ•œ๊ณ„์™€ Supabase ์ „ํ™˜

ํ˜„์žฌ ๊ตฌ์„ฑ์˜ ํ•œ๊ณ„

ํ•ญ๋ชฉ ํ•œ๊ณ„ ์‹ค์ œ ์—ฌ์œ 
GitHub Actions Public ๋ฌด์ œํ•œ / Private ์›” 2,000๋ถ„ ํ•˜๋ฃจ 5~10๋ถ„ โ†’ Public ์ด๋ฉด ๊ฑฑ์ • ์—†์Œ
์ €์žฅ์†Œ ์šฉ๋Ÿ‰ ๊ถŒ์žฅ 1GB, ๊ฒฝ๊ณ  5GB CVE 1๊ฑด โ‰ˆ 1KB โ†’ 10๋งŒ ๊ฑด์ด์–ด๋„ 100MB ์ˆ˜์ค€
SQLite ํŒŒ์ผ ์ปค๋ฐ‹ ๋งค์ผ ๋ฐ”์ด๋„ˆ๋ฆฌ 1๊ฐœ๊ฐ€ ์ปค๋ฐ‹๋˜์–ด ํžˆ์Šคํ† ๋ฆฌ๊ฐ€ ์Œ“์ž„ ํ•˜๋ฃจ ์ˆ˜์‹ญ~์ˆ˜๋ฐฑKB. ์ˆ˜๋…„์€ ๋ฒ„ํŒ๋‹ˆ๋‹ค
GitHub Pages ์ €์žฅ์†Œ 1GB, ์›” 100GB ์ „์†ก ์ •์  HTML ์ด๋ผ ์—ฌ์œ 
NVD API ํ‚ค ์—†์ด 30์ดˆ๋‹น 5์š”์ฒญ 55์ข… ร— 1์š”์ฒญ โ‰ˆ 6๋ถ„. ํ‚ค ์žˆ์œผ๋ฉด 1๋ถ„
Gmail SMTP ํ•˜๋ฃจ 500ํ†ต ์ˆ˜์‹ ์ž ์ˆ˜ ร— 1ํ†ต

์–ธ์ œ ์˜ฎ๊ฒจ์•ผ ํ•˜๋‚˜

  • CVE ๋ˆ„์ ์ด 10๋งŒ ๊ฑด์„ ๋„˜์–ด data/cve.db ๊ฐ€ ์ˆ˜๋ฐฑ MB๊ฐ€ ๋  ๋•Œ
  • ์ €์žฅ์†Œ ํžˆ์Šคํ† ๋ฆฌ ์šฉ๋Ÿ‰์ด ๋ถ€๋‹ด๋  ๋•Œ (๋งค์ผ ์ปค๋ฐ‹๋˜๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ๋ผ ํžˆ์Šคํ† ๋ฆฌ๊ฐ€ ๋ˆ„์ ๋ฉ๋‹ˆ๋‹ค)
  • ์—ฌ๋Ÿฌ ์‹œ์Šคํ…œ์—์„œ ๋™์‹œ์— DB๋ฅผ ์ฝ๊ณ  ์จ์•ผ ํ•  ๋•Œ

Supabase(๋ฌด๋ฃŒ Postgres) ์ „ํ™˜ ๋ฐฉ๋ฒ•

store.py ๋Š” Store ์ถ”์ƒ ํด๋ž˜์Šค + SqliteStore ๊ตฌํ˜„์œผ๋กœ ๋‚˜๋‰˜์–ด ์žˆ์–ด ํŒŒ์ผ 1๊ฐœ๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๊ต์ฒด๋ฉ๋‹ˆ๋‹ค.

  1. https://supabase.com ๊ฐ€์ž… โ†’ ์ƒˆ ํ”„๋กœ์ ํŠธ โ†’ Settings โ†’ Database โ†’ Connection string ๋ณต์‚ฌ (๋ฌด๋ฃŒ ํ‹ฐ์–ด: 500MB DB, ํ”„๋กœ์ ํŠธ 2๊ฐœ)
  2. requirements.txt ์— psycopg2-binary==2.9.9 ์ถ”๊ฐ€
  3. src/aicve/store_supabase.py ๋ฅผ ๋งŒ๋“ค๊ณ  Store ๋ฅผ ์ƒ์†ํ•ด ์•„๋ž˜ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
    from .store import Store
    
    class SupabaseStore(Store):
        def init_schema(self): ...        # store.py ์˜ SCHEMA ๋ฅผ Postgres ๋ฌธ๋ฒ•์œผ๋กœ
        def start_run(self, run_id, scope): ...
        def finish_run(self, run_id, **fields): ...
        def upsert_findings(self, findings, run_id): ...   # ON CONFLICT DO UPDATE
        def fetch_run_cves(self, run_id): ...
        def fetch_all_cves(self, limit=None): ...
        def fetch_runs(self, limit=30): ...
        def log_mail(self, run_id, recipient, subject, status, error_msg="", attach_file=""): ...
        def fetch_mail_logs(self, run_id=None): ...
        def close(self): ...
    SQL ๋ฌธ๋ฒ• ์ฐจ์ด๋Š” ์„ธ ๊ตฐ๋ฐ๋ฟ์ž…๋‹ˆ๋‹ค: INTEGER PRIMARY KEY AUTOINCREMENT โ†’ SERIAL PRIMARY KEY, INSERT OR REPLACE โ†’ INSERT ... ON CONFLICT (cve_id, sw_name) DO UPDATE SET ..., ํ”Œ๋ ˆ์ด์Šคํ™€๋” ? โ†’ %s.
  4. main.py ์—์„œ ์ƒ์„ฑ ๋ถ€๋ถ„ ํ•œ ์ค„๋งŒ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.
    # store = SqliteStore(args.db)
    store = SupabaseStore(os.environ["DATABASE_URL"])
  5. DATABASE_URL ์„ GitHub Secrets ์— ๋“ฑ๋กํ•˜๊ณ , ์›Œํฌํ”Œ๋กœ์˜ ์ปค๋ฐ‹ ๋‹จ๊ณ„์—์„œ data/ ๋ฅผ ์ œ์™ธํ•ฉ๋‹ˆ๋‹ค.

site.py ๋Š” ํ†ต๊ณ„์šฉ ๋ฉ”์„œ๋“œ(severity_countsยทsw_countsยทmail_stat_by_runยทtotal_cve_count)๋„ ์”๋‹ˆ๋‹ค. ํ•จ๊ป˜ ์˜ฎ๊ธฐ๊ฑฐ๋‚˜, ์šฐ์„  SqliteStore ๋ฅผ ์ƒ์†ํ•ด ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ๋ฎ์–ด์จ๋„ ๋ฉ๋‹ˆ๋‹ค.


7. ์ˆ˜์ง‘ ๋ฒ”์œ„(Scope) ์กฐ์ ˆํ•˜๊ธฐ

์ „๋Ÿ‰ ์ˆ˜์ง‘์€ NVD ๋ ˆ์ดํŠธ ๋ฆฌ๋ฐ‹ ๋•Œ๋ฌธ์— ๋А๋ฆฌ๊ณ , ์—‘์…€์ด ์ˆ˜๋ฐฑ ํ–‰์ด ๋˜๋ฉด ๋‚ด๋ถ€๋ง์—์„œ ๊ฒ€ํ† ๊ฐ€ ๋ฒ„๊ฒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ 9๊ฐœ ์ถ•์œผ๋กœ ๋ฒ”์œ„๋ฅผ ์ขํž ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# ์ถ• ํ‚ค / CLI ๊ธฐ๋ณธ๊ฐ’ ์„ค๋ช…
1 ๊ธฐ๊ฐ„ lookback_days / --lookback 3 ์ตœ๊ทผ N์ผ
2 ์ ˆ๋Œ€ ๊ตฌ๊ฐ„ date_fromยทdate_to / --fromยท--to ์—†์Œ ์ง€์ • ์‹œ โ‘ ์„ ๋ฌด์‹œ
3 ์‹ฌ๊ฐ๋„ ํ•˜ํ•œ min_severity / --min-severity MEDIUM ALL ์ด๋ฉด ํ•„ํ„ฐ ์•ˆ ํ•จ
4 ๋Œ€์ƒ ๊ทธ๋ฃน groups / --groups all framework,serving,ui โ€ฆ
5 ๋Œ€์ƒ S/W sw_names / --sw-names ์—†์Œ ์ง€์ • ์‹œ โ‘ฃโ‘ฅ์„ ๋ฌด์‹œ
6 ๋ฐ˜์ž…๋ถ„ ํ•œ์ • only_in_use / --only-in-use false in_use: true ๋งŒ
7 ์†Œ์Šค sources / --sources nvd,osv,ghsa,kev ์ผ๋ถ€๋งŒ ์„ ํƒ ๊ฐ€๋Šฅ
8 ๊ฒฐ๊ณผ ๋ฒ”์œ„ excel_scope / --excel-scope delta delta=์‹ ๊ทœยท๋ณ€๊ฒฝ๋งŒ / all=์ „๋Ÿ‰
9 ์ตœ๋Œ€ ํ–‰์ˆ˜ max_rows / --max-rows 300 ์ดˆ๊ณผ๋ถ„์€ ์‹ฌ๊ฐ๋„ยท์ ์ˆ˜ ์ˆœ์œผ๋กœ ์ž˜๋ผ๋ƒ„

์šฐ์„ ์ˆœ์œ„: settings.yml ๊ธฐ๋ณธ๊ฐ’ โ†’ preset โ†’ CLI/Actions ์ž…๋ ฅ (๋’ค๊ฐ€ ์•ž์„ ๋ฎ์–ด์”€). ๋นˆ ๊ฐ’("")์€ ์•ž ๋‹จ๊ณ„๋ฅผ ๋ฎ์–ด์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์•Œ์•„ ๋‘๋ฉด ์ข‹์€ ๊ทœ์น™

  • KEV(์‹ค์ œ ์•…์šฉ ํ™•์ธ) ๋“ฑ์žฌ ๊ฑด์€ ์‹ฌ๊ฐ๋„ ํ•˜ํ•œ๊ณผ ๋ฌด๊ด€ํ•˜๊ฒŒ ํ•ญ์ƒ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
  • sw_names ๋ฅผ ์ฃผ๋ฉด groupsยทonly_in_use ๋Š” ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค(๊ฐ€์žฅ ์ข์€ ์กฐ๊ฑด์ด ์ด๊น๋‹ˆ๋‹ค).
  • ๋Œ€์ƒ์ด 0๊ฑด์ด๋ฉด ์ฆ‰์‹œ ์ข…๋ฃŒํ•˜๊ณ  run_log.status='SKIPPED' ์™€ ์‚ฌ์œ ๋ฅผ ๋‚จ๊น๋‹ˆ๋‹ค.
  • ํ™•์ •๋œ ์กฐ๊ฑด์€ ์‹คํ–‰ ๋กœ๊ทธ ์ฒซ ์ค„, run_log.scope_desc, ์—‘์…€ META, ๋ฉ”์ผ ๋ณธ๋ฌธ ์ƒ๋‹จ์— ๋˜‘๊ฐ™์€ ํ•œ ์ค„๋กœ ์‹ค๋ฆฝ๋‹ˆ๋‹ค.
    SCOPE lookback=3 sev>=HIGH groups=serving,ui sw=- in_use=False src=osv,kev scope=delta max=300
    

ํ”„๋ฆฌ์…‹ (settings.yml: presets)

์ด๋ฆ„ ์กฐํ•ฉ ์“ฐ์ž„์ƒˆ
daily 3์ผ / MEDIUM ์ด์ƒ / delta / 300ํ–‰ ๊ธฐ๋ณธ ์ผ์ผ ์ˆ˜์ง‘
urgent 1์ผ / HIGH ์ด์ƒ / delta / 50ํ–‰ ๊ธ‰ํ•  ๋•Œ ๋น ๋ฅด๊ฒŒ
in_use 7์ผ / LOW ์ด์ƒ / ๋ฐ˜์ž…๋ถ„๋งŒ / 200ํ–‰ ๋‚ด๋ถ€๋ง ๋ฐ˜์ž… S/W ์ง‘์ค‘ ์ ๊ฒ€
monthly 30์ผ / HIGH ์ด์ƒ / ์ „๋Ÿ‰ / 1000ํ–‰ ์›”๊ฐ„ ๋ณด๊ณ ์šฉ
backfill 2026-01-01~ / HIGH ์ด์ƒ / ์ „๋Ÿ‰ / 5000ํ–‰ ์ตœ์ดˆ 1ํšŒ ๊ณผ๊ฑฐ ๋ฐ์ดํ„ฐ ์ฑ„์šฐ๊ธฐ

8. CLI ์‚ฌ์šฉ๋ฒ•

# ๋กœ์ปฌ ์‹คํ–‰ ์ค€๋น„
python -m venv .venv && .venv/Scripts/activate      # Linux/Mac: source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env                                 # ๊ฐ’์„ ์ฑ„์šฐ๊ณ  ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ export
# ์กฐ๊ฑด๋งŒ ํ™•์ธ (API ํ˜ธ์ถœ ์—†์Œ) โ€” ์‹ค์ˆ˜ ๋ฐฉ์ง€์šฉ์œผ๋กœ ํ•ญ์ƒ ๋จผ์ € ๋Œ๋ ค ๋ณด์„ธ์š”
python -m src.aicve.main --show-scope --preset urgent --groups serving,ui

# ๊ธฐ๋ณธ ์ผ์ผ ์ˆ˜์ง‘
python -m src.aicve.main --preset daily

# ํŠน์ • S/W๋งŒ, ๋ฉ”์ผ ์—†์ด
python -m src.aicve.main --sw-names "PyTorch,vLLM" --skip-mail

# ๋ฉ”์ผ ๋ฐœ์†ก ์—†์ด ๋ณธ๋ฌธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋งŒ ์ €์žฅ (output/mail_preview_*.html)
python -m src.aicve.main --preset daily --dry-run

# ๊ณผ๊ฑฐ ๊ตฌ๊ฐ„ ๋ฐฑํ•„ (์ „๋Ÿ‰ ์—‘์…€)
python -m src.aicve.main --from 2026-01-01 --to 2026-06-30 --excel-scope all --max-rows 5000

# ์ฒซ ์‹คํ–‰ 30์ผ์น˜
python -m src.aicve.main --backfill 30

์ „์ฒด ์˜ต์…˜

--preset {daily|urgent|in_use|monthly|backfill}
--lookback N          --backfill N        --from YYYY-MM-DD    --to YYYY-MM-DD
--min-severity {CRITICAL|HIGH|MEDIUM|LOW|ALL}
--groups framework,serving                --sw-names PyTorch,vLLM      --only-in-use
--sources nvd,osv,ghsa,kev                --excel-scope {delta|all}    --max-rows N
--skip-mail           --dry-run           --show-scope         --skip-site
--config / --watchlist / --db / --out-dir / --docs-dir / --templates / --mail-list

๊ฒฐ๊ณผ ํ™•์ธ (DB ์กฐํšŒ)

"๋ฉ”์ผ์ด ์‹ค์ œ๋กœ ๋‚˜๊ฐ”๋‚˜", "์ง€๋‚œ์ฃผ์— ๋ญ˜ ๋ณด๋ƒˆ๋‚˜" ๋ฅผ ํ™•์ธํ•˜๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ฝ๊ธฐ ์ „์šฉ์ด๋ผ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

python -m src.aicve.report                      # ์ตœ๊ทผ ์‹คํ–‰ + ๋ฉ”์ผ ์„ฑ๊ณต/์‹คํŒจ ์š”์•ฝ
python -m src.aicve.report --mails              # ๋ฉ”์ผ ๋ฐœ์†ก ๋กœ๊ทธ ์ „์ฒด (์ˆ˜์‹ ์žยท์‹œ๊ฐยท์ƒํƒœ)
python -m src.aicve.report --run 20260816211121 # ํŠน์ • ํšŒ์ฐจ ์ƒ์„ธ (CVE ๋ชฉ๋ก + ๋ฐœ์†ก ๋กœ๊ทธ)
python -m src.aicve.report --cves               # ๋ˆ„์  CVE ๋ชฉ๋ก
python -m src.aicve.report --stats              # ์‹ฌ๊ฐ๋„ยทS/W๋ณ„ ํ†ต๊ณ„
python -m src.aicve.report --sql "SELECT * FROM mail_log WHERE status='FAILED'"

์ตœ์‹  DB ๋ฅผ ๋ณด๋ ค๋ฉด ์‹คํ–‰ ์ „์— git pull ๋กœ ์ €์žฅ์†Œ๋ฅผ ๋ฐ›์•„ ๋‘์„ธ์š”(์›Œํฌํ”Œ๋กœ๊ฐ€ ๋งค์ผ data/cve.db ๋ฅผ ์ปค๋ฐ‹ํ•ฉ๋‹ˆ๋‹ค).

๊ฐ™์€ ๋‚ด์šฉ์„ ์—ด๋žŒ ํŽ˜์ด์ง€ ์—์„œ๋„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ค์น˜ ์—†์ด ๋ณด๋ ค๋ฉด ๋Œ€์‹œ๋ณด๋“œ ์‹คํ–‰ ์ด๋ ฅ ํ‘œ์˜ ๋ฉ”์ผ(์„ฑ๊ณต/์‹คํŒจ) ์นธ๊ณผ ๋ณด๊ธฐ ๋งํฌ๋ฅผ ์“ฐ์„ธ์š”. GUI ๋กœ DB ๋ฅผ ์ง์ ‘ ์—ด์–ด ๋ณด๊ณ  ์‹ถ์œผ๋ฉด ๋ฌด๋ฃŒ ํ”„๋กœ๊ทธ๋žจ DB Browser for SQLite ์—์„œ data/cve.db ๋ฅผ ์—ด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์†Œ์Šค๋ณ„ ๋‹จ๋… ์‹คํ–‰ (๋””๋ฒ„๊น…์šฉ)

python -m src.aicve.sources.kev
python -m src.aicve.sources.osv  --sw-names "vLLM" --lookback 90
python -m src.aicve.sources.nvd  --sw-names "PyTorch" --lookback 30
python -m src.aicve.sources.ghsa --groups ui --lookback 30      # GITHUB_TOKEN ํ•„์š”
python -m src.aicve.site                                        # ์ˆ˜์ง‘ ์—†์ด docs/ ๋งŒ ์žฌ์ƒ์„ฑ

ํ…Œ์ŠคํŠธ

python -m pytest tests/ -q

tests/test_version_range.py ๋Š” ๋ฒ„์ „๋ฒ”์œ„ ๋ณ€ํ™˜์„ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด ์ƒ์„ฑ๋ฟ ์•„๋‹ˆ๋ผ "์ด ๋ฒ”์œ„์— 1.4.1 ์€ ํฌํ•จ๋˜๊ณ  1.4.2 ๋Š” ๋น ์ง€๋Š”๊ฐ€"๊นŒ์ง€ ํ™•์ธํ•ด, ํ‘œ๊ธฐ๋งŒ ๋งž๊ณ  ์˜๋ฏธ๊ฐ€ ํ‹€๋ฆฌ๋Š” ์‚ฌ๊ณ ๋ฅผ ๋ง‰์Šต๋‹ˆ๋‹ค.

์ข…๋ฃŒ ์ฝ”๋“œ

์ฝ”๋“œ ์˜๋ฏธ
0 SUCCESS / PARTIAL(์ผ๋ถ€ ์†Œ์Šค ์‹คํŒจ) / SKIPPED(๋Œ€์ƒ 0๊ฑด)
1 FAILED โ€” Actions ๊ฐ€ ์‹คํŒจ ์•Œ๋ฆผ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค

์–ด๋–ค ๋‹จ๊ณ„๊ฐ€ ์‹คํŒจํ•ด๋„ ๋‚˜๋จธ์ง€๋Š” ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์†Œ์Šค ํ•˜๋‚˜๊ฐ€ ์ฃฝ์œผ๋ฉด ๋‚˜๋จธ์ง€ ์†Œ์Šค๋กœ ๊ณ„์†ํ•˜๊ณ , ๋ฉ”์ผ์ด ์‹คํŒจํ•ด๋„ ์—‘์…€ยทDBยทํŽ˜์ด์ง€๋Š” ์ •์ƒ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.


9. ์ €์žฅ์†Œ ๊ตฌ์กฐ

ai-cve-watch/
โ”œโ”€โ”€ .github/workflows/daily.yml   ๋งค์ผ 06:00 KST ์ž๋™ ์‹คํ–‰ + ์ˆ˜๋™ ์‹คํ–‰
โ”œโ”€โ”€ config/
โ”‚   โ”œโ”€โ”€ watchlist.yml             โ˜… ๊ฐ์‹œ ๋Œ€์ƒ 55์ข… (ํ•ต์‹ฌ ์„ค์ •)
โ”‚   โ””โ”€โ”€ settings.yml              ๊ธฐ๋ณธ๊ฐ’ + ํ”„๋ฆฌ์…‹ + ์žฌ์‹œ๋„ ์„ค์ •
โ”œโ”€โ”€ mail_list.txt                 ์ˆ˜์‹ ์ž (1์ค„ 1๊ฐœ, '#' ์ฃผ์„ ํ—ˆ์šฉ)
โ”œโ”€โ”€ src/aicve/
โ”‚   โ”œโ”€โ”€ main.py                   ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜ ์ง„์ž…์  (CLI)
โ”‚   โ”œโ”€โ”€ scope.py                  โ˜… ์ˆ˜์ง‘ ๋ฒ”์œ„ ํ™•์ • (settings โ†’ preset โ†’ CLI)
โ”‚   โ”œโ”€โ”€ sources/
โ”‚   โ”‚   โ”œโ”€โ”€ base.py               ์žฌ์‹œ๋„ยท๋ฐฑ์˜คํ”„๊ฐ€ ๋ถ™์€ HTTP ํด๋ผ์ด์–ธํŠธ
โ”‚   โ”‚   โ”œโ”€โ”€ nvd.py                NVD CVE API 2.0   (CVSSยท์š”์•ฝ์ด ์ •ํ™•)
โ”‚   โ”‚   โ”œโ”€โ”€ osv.py                OSV.dev           (โ˜… ๋ฒ„์ „๋ฒ”์œ„๊ฐ€ ๊ฐ€์žฅ ์ •ํ™•)
โ”‚   โ”‚   โ”œโ”€โ”€ ghsa.py               GitHub Advisory GraphQL
โ”‚   โ”‚   โ””โ”€โ”€ kev.py                CISA ์‹ค์ œ ์•…์šฉ ๋ชฉ๋ก โ†’ KEV_YN
โ”‚   โ”œโ”€โ”€ normalize.py              โ˜… ๊ณตํ†ต ์Šคํ‚ค๋งˆ + ๋ฒ„์ „๋ฒ”์œ„ ๋ณ€ํ™˜ + CVSS ๊ณ„์‚ฐ
โ”‚   โ”œโ”€โ”€ excel.py                  โ˜… CVE_YYYYMMDD.xls / .xlsx / .csv
โ”‚   โ”œโ”€โ”€ mailer.py                 SMTP ๊ฐœ๋ณ„ ๋ฐœ์†ก + ๊ฒฐ๊ณผ ๊ธฐ๋ก
โ”‚   โ”œโ”€โ”€ store.py                  Store ์ถ”์ƒ + SqliteStore (Supabase ๊ต์ฒด ์ง€์ )
โ”‚   โ”œโ”€โ”€ site.py                   Jinja2 โ†’ docs/ ์ •์  ํŽ˜์ด์ง€
โ”‚   โ””โ”€โ”€ logutil.py                ๋กœ๊น… + ๋น„๋ฐ€์ •๋ณด ๋งˆ์Šคํ‚น
โ”œโ”€โ”€ templates/                    base / index / run / cve / mail (.html.j2)
โ”œโ”€โ”€ data/cve.db                   SQLite (์ปค๋ฐ‹ ๋Œ€์ƒ)
โ”œโ”€โ”€ output/                       CVE_YYYYMMDD.xls (์ปค๋ฐ‹ ๋Œ€์ƒ, 90์ผ ๋ณด๊ด€)
โ”œโ”€โ”€ docs/                         GitHub Pages ์‚ฐ์ถœ๋ฌผ (์ปค๋ฐ‹ ๋Œ€์ƒ)
โ””โ”€โ”€ tests/                        pytest

๋ฐ์ดํ„ฐ ๋ณ‘ํ•ฉ ๊ทœ์น™

๋™์ผ (CVE_ID, SW_NAME) ์€ 1ํ–‰์œผ๋กœ ํ•ฉ์นฉ๋‹ˆ๋‹ค.

ํ•„๋“œ ์šฐ์„ ์ˆœ์œ„ ์ด์œ 
๋ฒ„์ „๋ฒ”์œ„ ยท ์กฐ์น˜๋ฒ„์ „ OSV > GHSA > NVD OSV ๊ฐ€ ํŒจํ‚ค์ง€ ๋ฒ„์ „ ์ •๋ณด๋ฅผ ๊ฐ€์žฅ ์ •ํ™•ํžˆ ๊ด€๋ฆฌ
CVSS ยท ์š”์•ฝ ยท ์ฐธ๊ณ URL NVD > GHSA > OSV NVD ๊ฐ€ ๊ณต์‹ ์ ์ˆ˜ยท์„ค๋ช…์„ ์ œ๊ณต

SEVERITY ๋Š” CVSS v3.1 ์ ์ˆ˜ ๊ธฐ์ค€(9.0โ†‘ CRITICAL / 7.0โ†‘ HIGH / 4.0โ†‘ MEDIUM / 0.1โ†‘ LOW)์ด๋ฉฐ, ์ ์ˆ˜๊ฐ€ ์—†์œผ๋ฉด ๋ฒกํ„ฐ์—์„œ ์ง์ ‘ ๊ณ„์‚ฐํ•˜๊ณ , ๊ทธ๊ฒƒ๋„ ์—†์œผ๋ฉด ์†Œ์Šค๊ฐ€ ์ค€ ๋“ฑ๊ธ‰ ๋ฌธ์ž์—ด์„ ์”๋‹ˆ๋‹ค.

์‹ ๊ทœ/๋ณ€๊ฒฝ ํŒ์ •

content_hash = sha256(affected_range|fixed_version|severity|cvss_score|summary) โ†’ ๊ธฐ์กด ํ–‰๊ณผ ๋‹ค๋ฅด๋ฉด ๋ณ€๊ฒฝ(updated), ํ–‰ ์ž์ฒด๊ฐ€ ์—†์œผ๋ฉด ์‹ ๊ทœ(new). ์—‘์…€ยท๋ฉ”์ผ์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋ฒˆ ์‹คํ–‰์˜ ์‹ ๊ทœยท๋ณ€๊ฒฝ ๊ฑด๋งŒ ๋‹ด๊น๋‹ˆ๋‹ค(excel_scope: delta).


10. ๋ฌธ์ œ ํ•ด๊ฒฐ

์ฆ์ƒ ์›์ธ๊ณผ ํ•ด๊ฒฐ
๋ฉ”์ผ์ด ์•ˆ ์˜ด โ‘  ์‹ ๊ทœ 0๊ฑด์ด๋ฉด ๋ฐœ์†กํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์ •์ƒ). settings.yml: send_when_empty: true ๋กœ ๋ฐ”๊พธ๋ฉด ํ•ญ์ƒ ๋ฐœ์†ก โ‘ก SMTP_PASS ์— ์•ฑ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋Œ€์‹  ๊ณ„์ • ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋„ฃ์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธ โ‘ข ์‹คํ–‰ ์ƒ์„ธ ํŽ˜์ด์ง€์˜ ๋ฉ”์ผ ๋ฐœ์†ก ๋กœ๊ทธ ์—์„œ ์‹คํŒจ ์‚ฌ์œ  ํ™•์ธ
Pages ๊ฐ€ 404 Settings โ†’ Pages ์˜ ํด๋”๊ฐ€ /docs ์ธ์ง€, docs/index.html ์ด ์ปค๋ฐ‹๋๋Š”์ง€ ํ™•์ธ
Pages ์„ค์ •์—์„œ /docs ๋ฅผ ๋ชป ๊ณ ๋ฆ„ Branch ๊ฐ€ None ๋ฟ์ด๋ฉด ์ €์žฅ์†Œ๊ฐ€ ๋น„์–ด ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ push ํ•˜๊ณ  ์›Œํฌํ”Œ๋กœ๋ฅผ 1ํšŒ ๋Œ๋ ค docs/ ๋ฅผ ๋งŒ๋“  ๋’ค ๋‹ค์‹œ ์˜ค์„ธ์š” (1์žฅ โ‘ฃโ‘ค)
NVD ์ˆ˜์ง‘์ด ๋งค์šฐ ๋А๋ฆผ ์ •์ƒ์ž…๋‹ˆ๋‹ค(ํ‚ค ์—†์œผ๋ฉด ์š”์ฒญ ๊ฐ„ 6.5์ดˆ). NVD_API_KEY ๋ฅผ ๋“ฑ๋กํ•˜๋ฉด 6๋ฐฐ ๋นจ๋ผ์ง‘๋‹ˆ๋‹ค
GHSA ๊ฐ€ ํ•ญ์ƒ 0๊ฑด GITHUB_TOKEN ์ด ์—†์œผ๋ฉด ์ด ์†Œ์Šค๋งŒ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค. ๋กœ์ปฌ ์‹คํ–‰ ์‹œ์—๋Š” PAT ๋ฅผ ์ง์ ‘ ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค
์›Œํฌํ”Œ๋กœ๊ฐ€ ์•ˆ ๋Œ์•„๊ฐ 4์žฅ 60์ผ ์ž๋™ ๋น„ํ™œ์„ฑํ™” ์ฐธ๊ณ 
์—‘์…€ ํ–‰์ด ์ž˜๋ฆผ META ์˜ TRUNCATED_CNT ํ™•์ธ โ†’ --max-rows ๋ฅผ ์˜ฌ๋ฆฌ๊ฑฐ๋‚˜ ์กฐ๊ฑด์„ ์ขํžˆ์„ธ์š”
SUMMARY ์•ž์— [๋ฒ„์ „๋ฒ”์œ„ ๋ถˆ๋ช…ํ™•] ์–ด๋А ์†Œ์Šค๋„ ๋ฒ„์ „ ๋ฒ”์œ„๋ฅผ ์ฃผ์ง€ ์•Š์•„ * ๋กœ ๊ธฐ๋ก๋œ ๊ฑด์ž…๋‹ˆ๋‹ค. ์ˆ˜๋™ ํ™•์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค
์ปค๋ฐ‹ ์ถฉ๋Œ๋กœ ํ‘ธ์‹œ ์‹คํŒจ ์›Œํฌํ”Œ๋กœ๊ฐ€ pull --rebase ๋กœ 3ํšŒ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. ๊ณ„์† ์‹คํŒจํ•˜๋ฉด ์ˆ˜๋™ ์‹คํ–‰์œผ๋กœ ์žฌ์‹œ๋„ํ•˜์„ธ์š”
๋กœ์ปฌ์—์„œ ํ•œ๊ธ€์ด ๊นจ์ง Windows ์ฝ˜์†”์ด๋ฉด set PYTHONIOENCODING=utf-8 ํ›„ ์‹คํ–‰

๋กœ๊ทธ ๋ณด๋Š” ๋ฒ•

  • Actions ๋กœ๊ทธ: ์ €์žฅ์†Œ โ†’ Actions โ†’ ํ•ด๋‹น ์‹คํ–‰ โ†’ ์ˆ˜์ง‘ ์‹คํ–‰ ์Šคํ…
  • ํŒŒ์ผ ๋กœ๊ทธ: ์‹คํ–‰ ์‚ฐ์ถœ๋ฌผ(artifact) cve-output-* ์•ˆ์˜ logs/run_*.log (30์ผ ๋ณด๊ด€)
  • ๋น„๋ฐ€๋ฒˆํ˜ธยทํ† ํฐยท๋ฉ”์ผ ์ฃผ์†Œ๋Š” ๊ธฐ๋ก ์ง์ „์— ์ž๋™ ๋งˆ์Šคํ‚น๋˜๋ฏ€๋กœ ๋กœ๊ทธ๊ฐ€ ๊ณต๊ฐœ๋ผ๋„ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

11. SUMMARY ํ•œ๊ตญ์–ด ๋ฒˆ์—ญ

์ทจ์•ฝ์  ์„ค๋ช…(SUMMARY)์€ ์›๋ž˜ ์˜๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์œผ๋กœ ํ•œ๊ตญ์–ด ๋ฒˆ์—ญ์ด ์ผœ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

# config/settings.yml
output:
  translate:
    enabled: true
    provider: google        # google(ํ‚ค ๋ถˆํ•„์š”) / papago / deepl / none
    mode: replace           # replace = ํ•œ๊ตญ์–ด๋งŒ / append = ํ•œ๊ตญ์–ด + ์˜๋ฌธ ์›๋ฌธ

์–ด๋””์— ์–ด๋–ป๊ฒŒ ๋ฐ˜์˜๋˜๋‚˜

์œ„์น˜ ๋‚ด์šฉ
์—‘์…€ SUMMARY ํ•œ๊ตญ์–ด (ํ—ค๋” 16๊ฐœ ๊ทœ๊ฒฉ์€ ๊ทธ๋Œ€๋กœ โ€” ์ปฌ๋Ÿผ์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค)
๋ฉ”์ผ ๋ณธ๋ฌธ ํ•œ๊ตญ์–ด
์—ด๋žŒ ํŽ˜์ด์ง€ ํ•œ๊ตญ์–ด + ์˜๋ฌธ ์›๋ฌธ ์„ ํŽผ์ณ ๋ณด๊ธฐ ๊ฐ€๋Šฅ
DB cve.summary_en ์˜๋ฌธ ์›๋ฌธ ํ•ญ์ƒ ๋ณด์กด

๊ฒ€์ƒ‰์€ ํ•œ๊ตญ์–ดยท์˜๋ฌธ ์–ด๋А ์ชฝ์œผ๋กœ๋„ ๋ฉ๋‹ˆ๋‹ค.

๋ฒˆ์—ญ ๋น„์šฉ๊ณผ ํ•œ๋„

ํ•œ ๋ฒˆ ๋ฒˆ์—ญํ•œ ๋ฌธ์žฅ์€ DB(translation ํ‘œ)์— ์บ์‹œ๋˜์–ด ๋‹ค์‹œ ๋ฒˆ์—ญํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋งค์ผ ์ƒˆ๋กœ ์žกํžˆ๋Š” ๊ฑด์ˆ˜๋งŒ ๋ฒˆ์—ญํ•˜๋ฏ€๋กœ(๋ณดํ†ต ์ˆ˜ ๊ฑด~์ˆ˜์‹ญ ๊ฑด) ๋ฌด๋ฃŒ ํ•œ๋„๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

์ œ๊ณต์ž ํ‚ค ํ•œ๋„ ๋น„๊ณ 
google (๊ธฐ๋ณธ) ๋ถˆํ•„์š” ๋ช…์‹œ ์—†์Œ ๋ฌด๋ฃŒ ์—”๋“œํฌ์ธํŠธ. ๋Œ€๋Ÿ‰ ์š”์ฒญ ์‹œ ์ผ์‹œ ์ฐจ๋‹จ๋  ์ˆ˜ ์žˆ์Œ
papago NAVER_CLIENT_ID/NAVER_CLIENT_SECRET 1๋งŒ์ž/์ผ ๋„ค์ด๋ฒ„ ๊ฐœ๋ฐœ์ž์„ผํ„ฐ ๋ฌด๋ฃŒ ๋“ฑ๋ก(์นด๋“œ ๋ถˆํ•„์š”)
deepl DEEPL_API_KEY 50๋งŒ์ž/์›” ํ’ˆ์งˆ์ด ๊ฐ€์žฅ ์ข‹์Œ. ๊ฐ€์ž… ์‹œ ์นด๋“œ ํ™•์ธ์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Œ

์ œ๊ณต์ž๋ฅผ ๋ฐ”๊พธ๋ ค๋ฉด settings.yml ์˜ provider ๋ฅผ ๊ณ ์น˜๊ณ , ํ•ด๋‹น ํ‚ค๋ฅผ GitHub Secrets ์— ๋„ฃ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์•ˆ์ „์žฅ์น˜

  • ๋ฒˆ์—ญ์ด ์‹คํŒจํ•ด๋„ ์‹คํ–‰์€ ๊ณ„์†๋ฉ๋‹ˆ๋‹ค. ์‹คํŒจํ•œ ๊ฑด์€ ์˜๋ฌธ ์›๋ฌธ์ด ๊ทธ๋Œ€๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.
  • CVE ๋ฒˆํ˜ธยทURL ์€ ๋ฒˆ์—ญ๊ธฐ์— ๋„˜๊ธฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. CVE-2026-1234 ๊ฐ€ ๊นจ์ง€์ง€ ์•Š๋„๋ก ์ž๋ฆฌํ‘œ์‹œ์ž๋กœ ๋นผ๋†จ๋‹ค๊ฐ€ ๋˜๋Œ๋ฆฝ๋‹ˆ๋‹ค.
  • [๋ฒ„์ „๋ฒ”์œ„ ๋ถˆ๋ช…ํ™•] ์ ‘๋‘์‚ฌ๋Š” ๋ฒˆ์—ญํ•˜์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฒˆ์—ญ์„ ์ผœ๊ณ  ๊บผ๋„ "๋ณ€๊ฒฝ" ์•Œ๋ฆผ์ด ์Ÿ์•„์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ ๊ฐ์ง€ ํ•ด์‹œ๋Š” ๋ฒˆ์—ญ๋ฌธ์ด ์•„๋‹ˆ๋ผ ์˜๋ฌธ ์›๋ฌธ์„ ๊ธฐ์ค€์œผ๋กœ ๊ณ„์‚ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด๋ฏธ ์Œ“์ธ ๊ฑด์„ ํ•œ ๋ฒˆ์— ๋ฒˆ์—ญํ•˜๊ธฐ

๋ฒˆ์—ญ์€ ๊ทธ ์‹คํ–‰์—์„œ ์ˆ˜์ง‘๋œ ๊ฑด์—๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋งค์ผ ์‹คํ–‰์€ ์ตœ๊ทผ ๋ฉฐ์น ์น˜๋งŒ ๋‹ค์‹œ ํ›‘๊ธฐ ๋•Œ๋ฌธ์—, ๋ฒˆ์—ญ์„ ์ผœ๊ธฐ ์ „์— ์Œ“์—ฌ ์žˆ๋˜ ๊ฑด์€ ๊ทธ๋Œ€๋กœ ์˜๋ฌธ์œผ๋กœ ๋‚จ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๋ช…๋ น์œผ๋กœ ํ•œ ๋ฒˆ์— ์ฑ„์›๋‹ˆ๋‹ค.

git pull                                        # ์ตœ์‹  DB ๋ฐ›๊ธฐ
python -m src.aicve.translate --backfill        # ์•„์ง ๋ฒˆ์—ญ ์•ˆ ๋œ ๊ฑด๋งŒ
python -m src.aicve.translate --retranslate     # ์ œ๊ณต์ž๋ฅผ ๋ฐ”๊ฟ” ์ „๋ถ€ ๋‹ค์‹œ ๋ฒˆ์—ญ
python -m src.aicve.translate "์˜๋ฌธ ๋ฌธ์žฅ"        # ํ•œ ๋ฌธ์žฅ๋งŒ ์‹œํ—˜ ๋ฒˆ์—ญ

์ด ์ž‘์—…์€ ๋ณ€๊ฒฝ ๊ฐ์ง€ ํ•ด์‹œ๋ฅผ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฒˆ์—ญ๋งŒ์œผ๋กœ ์ „ ๊ฑด์ด "๋ณ€๊ฒฝ"์œผ๋กœ ์žกํ˜€ ์•Œ๋ฆผ์ด ์Ÿ์•„์ง€๋Š” ์ผ์€ ์—†์Šต๋‹ˆ๋‹ค.

๋„๊ณ  ์‹ถ์œผ๋ฉด

output:
  translate:
    enabled: false     # ์˜๋ฌธ ์›๋ฌธ ๊ทธ๋Œ€๋กœ

์˜ค์—ญ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ ์กฐ์น˜ ํŒ๋‹จ์€ REFERENCE_URL ์˜ ์›๋ฌธ์„ ํ™•์ธํ•˜๊ณ  ํ•˜์‹œ๊ธธ ๊ถŒํ•ฉ๋‹ˆ๋‹ค. ๋ฒˆ์—ญ๋ฌธ์€ ๋น ๋ฅด๊ฒŒ ํ›‘์–ด๋ณด๋Š” ์šฉ๋„์ž…๋‹ˆ๋‹ค.


๋ผ์ด์„ ์Šค / ๋ฐ์ดํ„ฐ ์ถœ์ฒ˜

๊ฐ ์†Œ์Šค์˜ ์ด์šฉ์•ฝ๊ด€์„ ์ค€์ˆ˜ํ•ด ์ฃผ์„ธ์š”. ์ƒ์—…์  ์žฌ๋ฐฐํฌ ์‹œ์—๋Š” ์ถœ์ฒ˜ ํ‘œ๊ธฐ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages