Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions .github/workflows/auto-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
name: πŸ” PR Code Review

on:
pull_request:
types: [opened, synchronize, reopened]
branches:
- develop
- main

permissions:
contents: read
pull-requests: write

jobs:
code-review:
name: μ½”λ“œ λ³€κ²½ 뢄석 및 PM 리뷰 리포트 생성
runs-on: ubuntu-latest

steps:
# ── 전체 νžˆμŠ€ν† λ¦¬ 포함 체크아웃 ─────────
- name: Checkout (full history)
uses: actions/checkout@v4
with:
fetch-depth: 0 # diff μΆ”μΆœμ„ μœ„ν•΄ 전체 νžˆμŠ€ν† λ¦¬ ν•„μš”

# ── Python 및 뢄석 도ꡬ μ„€μΉ˜ ─────────────
- name: Python Setup
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install Analysis Tools
run: |
pip install pyflakes --quiet

# ── PR 메타 정보 ν™˜κ²½λ³€μˆ˜λ‘œ μ„ΈνŒ… ─────────
- name: Set Review Environment
run: |
echo "REVIEW_BASE_SHA=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_ENV"
echo "REVIEW_HEAD_SHA=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_ENV"
echo "REVIEW_BRANCH=${{ github.head_ref }}" >> "$GITHUB_ENV"
echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> "$GITHUB_ENV"

# base 브랜치λ₯Ό remoteμ—μ„œ κ°€μ Έμ™€μ„œ diff 기쀀점 확보
git fetch origin ${{ github.event.pull_request.base.ref }} --depth=1

# ── 핡심 뢄석 μ‹€ν–‰ ───────────────────────
- name: Run Code Review Analysis
id: analysis
run: |
python scripts/review_pr.py
continue-on-error: true # BLOCK이어도 μ½”λ©˜νŠΈλŠ” κ²Œμ‹œν•΄μ•Ό ν•˜λ―€λ‘œ

# ── PR μ½”λ©˜νŠΈλ‘œ κ²°κ³Ό κ²Œμ‹œ ────────────────
- name: Post Review Comment
if: always()
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');

// ── Markdown 리포트 읽기 ──
let body = '';
try {
body = fs.readFileSync('pr_review_result.md', 'utf8');
} catch {
body = '## ⚠️ μ½”λ“œ 리뷰 μ‹€ν–‰ μ‹€νŒ¨\n\n뢄석 슀크립트 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. Actions 둜그λ₯Ό ν™•μΈν•˜μ„Έμš”.';
}

// ── 인라인 μ½”λ©˜νŠΈ μΆ”κ°€ (BLOCK / HIGH 이슈) ──
let reviewData = { issues: [] };
try {
reviewData = JSON.parse(fs.readFileSync('pr_review_result.json', 'utf8'));
} catch {}

const headSha = context.payload.pull_request.head.sha;
const inlineIssues = (reviewData.issues || [])
.filter(i => ['BLOCK', 'HIGH'].includes(i.severity) && i.line > 0);

for (const issue of inlineIssues.slice(0, 20)) {
try {
await github.rest.pulls.createReviewComment({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
commit_id: headSha,
path: issue.file,
line: issue.line,
body: [
`**${issue.severity === 'BLOCK' ? '🚫' : 'πŸ”΄'} [${issue.severity}] ${issue.category}**`,
issue.message
].join('\n')
});
} catch (e) {
// 라인이 diff λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜λ©΄ 인라인 μ½”λ©˜νŠΈ μ‹€νŒ¨ β€” λ¬΄μ‹œ
}
}

// ── κΈ°μ‘΄ 봇 μ½”λ©˜νŠΈ μ—…λ°μ΄νŠΈ or μ‹ κ·œ 생성 ──
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

const existing = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('PR μ½”λ“œ 리뷰 β€”')
);

if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
}

# ── GitHub Actions Step Summary ──────────
- name: Write Step Summary
if: always()
run: |
if [ -f pr_review_result.md ]; then
cat pr_review_result.md >> "$GITHUB_STEP_SUMMARY"
fi

# ── BLOCK νŒμ • μ‹œ μ›Œν¬ν”Œλ‘œμš° μ‹€νŒ¨ 처리 ──
- name: Fail on BLOCK
if: steps.analysis.outcome == 'failure'
run: |
echo "::error title=μ½”λ“œ 리뷰 BLOCK::μžλ™ λΆ„μ„μ—μ„œ Mergeλ₯Ό 차단할 μ΄μŠˆκ°€ λ°œκ²¬λμŠ΅λ‹ˆλ‹€. PR μ½”λ©˜νŠΈλ₯Ό ν™•μΈν•˜μ„Έμš”."
exit 1
32 changes: 16 additions & 16 deletions Dynamic_RAG/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,25 +99,25 @@ python3 -m rag_fingerprint.main extract <extension_zip_or_dir> --output out/samp

## 탐지 μ‹ ν˜Έ μΉ΄ν…Œκ³ λ¦¬ (code_scanner.py)

| μΉ΄ν…Œκ³ λ¦¬ | μ˜ˆμ‹œ μ‹ ν˜Έ |
|----------|-----------|
| λ„€νŠΈμ›Œν¬ | `network.fetch`, `network.xhr`, `network.WebSocket`, `network.sendBeacon`, `network.axios` |
| λ©”μ‹œμ§• | `messaging.runtime.sendMessage`, `messaging.runtime.onMessage`, `messaging.tabs.sendMessage` |
| μŠ€ν† λ¦¬μ§€ | `storage.localStorage`, `storage.sessionStorage`, `storage.chrome.storage.local` |
| μ§€μ—° μ‹€ν–‰ | `delayed_execution.setInterval`, `delayed_execution.setTimeout` |
| 탐색 | `navigation.tabs.create`, `navigation.tabs.update`, `navigation.location.href` |
| 동적 μ‹€ν–‰ | `dynamic.eval`, `dynamic.new_function`, `dynamic.importScripts` |
| DOM | `dom.event.submit`, `dom.event.input`, `dom.selector.password`, `dom.selector.email` |
| μΉ΄ν…Œκ³ λ¦¬ | μ˜ˆμ‹œ μ‹ ν˜Έ |
| --------- | -------------------------------------------------------------------------------------------- |
| λ„€νŠΈμ›Œν¬ | `network.fetch`, `network.xhr`, `network.WebSocket`, `network.sendBeacon`, `network.axios` |
| λ©”μ‹œμ§• | `messaging.runtime.sendMessage`, `messaging.runtime.onMessage`, `messaging.tabs.sendMessage` |
| μŠ€ν† λ¦¬μ§€ | `storage.localStorage`, `storage.sessionStorage`, `storage.chrome.storage.local` |
| μ§€μ—° μ‹€ν–‰ | `delayed_execution.setInterval`, `delayed_execution.setTimeout` |
| 탐색 | `navigation.tabs.create`, `navigation.tabs.update`, `navigation.location.href` |
| 동적 μ‹€ν–‰ | `dynamic.eval`, `dynamic.new_function`, `dynamic.importScripts` |
| DOM | `dom.event.submit`, `dom.event.input`, `dom.selector.password`, `dom.selector.email` |

## Capability β†’ behavior_tags λ§€ν•‘ μ˜ˆμ‹œ

| μ‹ ν˜Έ μ‘°ν•© | behavior_tag |
|-----------|--------------|
| `content_script_run_at: document_start` | `early_injection` |
| `localStorage` + `network.fetch` | `session_theft_pattern`, `external_communication` |
| `runtime.sendMessage` | `message_passing_bridge` |
| `setInterval` | `repeated_exfiltration` |
| DNR `redirect` action | `redirect_hijacking`, `request_modification` |
| μ‹ ν˜Έ μ‘°ν•© | behavior_tag |
| --------------------------------------- | ------------------------------------------------- |
| `content_script_run_at: document_start` | `early_injection` |
| `localStorage` + `network.fetch` | `session_theft_pattern`, `external_communication` |
| `runtime.sendMessage` | `message_passing_bridge` |
| `setInterval` | `repeated_exfiltration` |
| DNR `redirect` action | `redirect_hijacking`, `request_modification` |

## vector λ²”μœ„ μ œμ™Έ κΈ°μ€€

Expand Down
Loading
Loading