Skip to content

๐ŸŸ [P1] fix(frontend): external links missing rel=noopener,noreferrer โ€” tabnapping vectorย #79

Description

@teddylee777

์ปจํ…์ŠคํŠธ ๋ธ”๋ก

Key Value
Category frontend
Checklist ISS-UI-R5 โ€” External links without rel="noopener noreferrer" (target="_blank")
Priority P1 ๐ŸŸ 
Scan Date 2026-04-16
Flagged By @code-review

์š”์•ฝ

  • WHAT: <a target=\"_blank\"> ๋‘ ๊ตฐ๋ฐ์— rel=\"noopener noreferrer\" ๋ˆ„๋ฝ + window.open(url, \"_blank\") ํ•œ ๊ตฐ๋ฐ์— \"noopener,noreferrer\" ์„ธ ๋ฒˆ์งธ ์ธ์ž ๋ˆ„๋ฝ โ€” ์ƒˆ ํƒญ์ด window.opener๋ฅผ ํ†ตํ•ด ์›๋ณธ ํŽ˜์ด์ง€ ์ œ์–ด ๊ฐ€๋Šฅ
  • WHY: tabnapping ๊ณต๊ฒฉ ๋ฒกํ„ฐ. ์‚ฌ์šฉ์ž๊ฐ€ ์™ธ๋ถ€ ๋งํฌ ํด๋ฆญ ํ›„ ์ƒˆ ํƒญ JS๊ฐ€ window.opener.location = \"phishing-url\"๋กœ ์›๋ณธ ํƒญ์„ ํ”ผ์‹ฑ ํŽ˜์ด์ง€๋กœ ์ „ํ™˜ ๊ฐ€๋Šฅ
  • WHERE: frontend/src/features/chat/components/thread/ThreadScrollUtils.tsx:61-66, frontend/src/features/chat/components/agent-inbox/components/ThreadActionsView.tsx:108
  • SEVERITY: HIGH โ€” ํฌ๋กœ์Šค ์‚ฌ์ดํŠธ ๊ณต๊ฒฉ ๋ฒกํ„ฐ

Evidence

# File Line Finding Flagged By Confidence
1 frontend/src/features/chat/components/thread/ThreadScrollUtils.tsx 61-66 <a target=\"_blank\">์— rel ์†์„ฑ ์—†์Œ (GitHub ๋งํฌ) @code-review High
2 frontend/src/features/chat/components/agent-inbox/components/ThreadActionsView.tsx 108 window.open(studioUrl, \"_blank\") โ€” \"noopener,noreferrer\" ์„ธ ๋ฒˆ์งธ ์ธ์ž ๋ˆ„๋ฝ @code-review High
3 (PASS ์ฐธ๊ณ ) MainLayoutClient.tsx:250-251, GenericInterrupt.tsx:30-31 โ€” ๋‹ค๋ฅธ ์™ธ๋ถ€ ๋งํฌ๋Š” ์˜ฌ๋ฐ”๋ฅด๊ฒŒ rel=\"noopener noreferrer\" ์„ค์ •๋จ โ€” ์ผ๊ด€์„ฑ ํ•„์š” @code-review High

์˜ํ–ฅ ๋ถ„์„

์˜ํ–ฅ ๋ฒ”์œ„

  • ์ฑ„ํŒ… UI ๋‚ด GitHub ๋งํฌ ํด๋ฆญํ•˜๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž
  • Agent Inbox์—์„œ LangGraph Studio ์ƒˆ ์ฐฝ ์—ฌ๋Š” admin/๊ฐœ๋ฐœ์ž

์žฅ์•  ์‹œ๋‚˜๋ฆฌ์˜ค

  1. ๊ณต๊ฒฉ์ž๊ฐ€ ํ”„๋กฌํ”„ํŠธ ์ธ์ ์…˜์œผ๋กœ LangGraph ์‘๋‹ต์ด ์•…์„ฑ ์™ธ๋ถ€ ๋งํฌ๋ฅผ ํฌํ•จํ•˜๊ฒŒ ์œ ๋„ (๋˜๋Š” GitHub ์ด์Šˆ ๋ณธ๋ฌธ์„ ์กฐ์ž‘)
  2. ์‚ฌ์šฉ์ž๊ฐ€ ๋งํฌ ํด๋ฆญ โ†’ ์ƒˆ ํƒญ์— ์•…์„ฑ ํŽ˜์ด์ง€ ๋กœ๋“œ
  3. ์•…์„ฑ ํŽ˜์ด์ง€์˜ JS๊ฐ€ window.opener.location = \"https://phishing-clone.com/login\" ์‹คํ–‰
  4. ์‚ฌ์šฉ์ž๊ฐ€ ๊ธฐ์กด ํƒญ์œผ๋กœ ๋Œ์•„์˜ค๋ฉด phishing ํŽ˜์ด์ง€ โ€” ์ž๊ฒฉ์ฆ๋ช… ์ž…๋ ฅ ์‹œ ํƒˆ์ทจ

๊ธด๊ธ‰๋„

  • ๋‹ค๋ฅธ ์™ธ๋ถ€ ๋งํฌ๋“ค์€ ์ด๋ฏธ noopener noreferrer๋ฅผ ์“ฐ๊ณ  ์žˆ์–ด ์ผ๊ด€์„ฑ ๋ถ€์กฑ
  • ์ˆ˜์ • ๋น„์šฉ ๊ทนํžˆ ๋‚ฎ์Œ (๊ฐ ํŒŒ์ผ 1-2์ค„)

์ œ์•ˆ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

์ ‘๊ทผ ๋ฐฉ๋ฒ•

ThreadScrollUtils.tsx:61-66:

// ๋ณ€๊ฒฝ ์ „
<a href={...} target=\"_blank\">...

// ๋ณ€๊ฒฝ ํ›„
<a href={...} target=\"_blank\" rel=\"noopener noreferrer\">...

ThreadActionsView.tsx:108:

// ๋ณ€๊ฒฝ ์ „
window.open(studioUrl, \"_blank\");

// ๋ณ€๊ฒฝ ํ›„
window.open(studioUrl, \"_blank\", \"noopener,noreferrer\");

ESLint ๊ทœ์น™ react/jsx-no-target-blank๋ฅผ ํ™œ์„ฑํ™”ํ•˜์—ฌ ์žฌ๋ฐœ ๋ฐฉ์ง€:

// frontend/eslint.config.js
rules: {
  \"react/jsx-no-target-blank\": \"error\",
}

๋Œ€์•ˆ

  • ๋ผ์šฐํ„ฐ ๊ธฐ๋ฐ˜ ํ•ธ๋“ค๋Ÿฌ: ์™ธ๋ถ€ ๋งํฌ๋ฅผ Next.js API๋กœ ํ”„๋ก์‹œ โ†’ ์Šค์ฝ”ํ”„ ๊ณผ๋Œ€
  • ์‚ฌ์šฉ์ž์—๊ฒŒ "์ƒˆ ์ฐฝ ์—ด๊ธฐ" ๊ฒฝ๊ณ : UX ์ €ํ•˜

์ˆ˜์šฉ ๊ธฐ์ค€

  • ThreadScrollUtils.tsx, ThreadActionsView.tsx ๋‘ ํŒŒ์ผ ์ˆ˜์ •
  • eslint.config.js์— react/jsx-no-target-blank: \"error\" ์ถ”๊ฐ€
  • cd frontend && pnpm lint ํ†ต๊ณผ
  • grep์œผ๋กœ target=\"_blank\" + ๋™์ผ ๋ผ์ธ์— rel= ์—†๋Š” ๊ฒฝ์šฐ 0๊ฑด ํ™•์ธ
  • ํ…Œ์ŠคํŠธ ์ปค๋งจ๋“œ: cd frontend && pnpm lint && pnpm test

์ฐธ์กฐ

์žฌํ˜„ ๋ฐฉ๋ฒ•

์‚ฌ์ „ ์กฐ๊ฑด

  • ๋กœ์ปฌ dev ์„œ๋ฒ„ ์‹คํ–‰ (pnpm dev)
  • ์ฑ„ํŒ… UI ์ ‘๊ทผ ๊ฐ€๋Šฅ

๋‹จ๊ณ„

  1. ์ฑ„ํŒ… ํƒญ์˜ GitHub ๋งํฌ ํ™•์ธ (ThreadScrollUtils)
  2. DevTools๋กœ <a> ์—˜๋ฆฌ๋จผํŠธ์˜ ์†์„ฑ ํ™•์ธ
  3. rel ์†์„ฑ ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ

๊ธฐ๋Œ€ ๊ฒฐ๊ณผ

rel=\"noopener noreferrer\" ์กด์žฌ

์‹ค์ œ ๊ฒฐ๊ณผ

rel ์†์„ฑ ์—†์Œ โ€” tabnapping ๊ฐ€๋Šฅ

๊ด€๋ จ ์ฝ”๋“œ ์ปจํ…์ŠคํŠธ

File Role Relevance
frontend/src/features/chat/components/thread/ThreadScrollUtils.tsx ์ฑ„ํŒ… ์Šคํฌ๋กค ์œ ํ‹ธ + ๋งํฌ ์ˆ˜์ • ๋Œ€์ƒ
frontend/src/features/chat/components/agent-inbox/components/ThreadActionsView.tsx Agent Inbox ์•ก์…˜ ๋ทฐ ์ˆ˜์ • ๋Œ€์ƒ
frontend/eslint.config.js ESLint ์„ค์ • ๊ทœ์น™ ํ™œ์„ฑํ™”

Detected by oh-my-braincrew `omb:issue` scan
Category: frontend | Scan date: 2026-04-16
`omb-issue-scan category=frontend checklist=ISS-UI-R5`

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions