Skip to content

Conversation

@manNomi
Copy link
Contributor

@manNomi manNomi commented Jan 5, 2026

관련 이슈

  • resolves: #이슈 번호

작업 내용

특이 사항

리뷰 요구사항 (선택)

@manNomi manNomi requested a review from wibaek as a code owner January 5, 2026 15:52
@coderabbitai
Copy link

coderabbitai bot commented Jan 5, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

  1. . github/workflows/pr-label-notify.yml 추가: PR 라벨 이벤트와 repository_dispatch를 수신하여 Discord 웹훅으로 알림을 전송하는 워크플로우가 추가되었습니다.
  2. lint-fix.prd.md 삭제: ESLint/Prettier 마이그레이션 계획 문서가 리포지토리에서 제거되었습니다.
  3. 클로드.md 추가: 이모지 기반 커밋 규칙과 원자적 커밋 가이드를 설명하는 새 문서가 추가되었습니다.
  4. .eslintignore 추가: 클로드.md를 ESLint 검사에서 제외하도록 설정되었습니다.
  5. .github/CODEOWNERS 수정: 글로벌 패턴의 소유자 목록에 추가 사용자가 포함되었습니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • wibaek

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning PR 설명이 템플릿 구조는 따르고 있으나, 관련 이슈를 제외한 모든 주요 섹션(작업 내용, 특이 사항, 리뷰 요구사항)이 비어있어 실질적인 정보가 부족합니다. 작업 내용 섹션에 각 파일의 목적(Discord webhook 알림 설정, 커밋 가이드라인)을 구체적으로 설명하고, 특이 사항과 리뷰 요구사항을 채워주세요.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 주요 변경사항(Discord webhook과 클로드.md 추가)을 명확하게 설명하며 PR의 핵심을 잘 요약하고 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55fa6f5 and 12ee0b2.

📒 Files selected for processing (3)
  • .github/CODEOWNERS
  • .github/workflows/pr-label-notify.yml
  • 클로드.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Fix all issues with AI Agents 🤖
In @.github/workflows/pr-label-notify.yml:
- Line 19: The workflow exposes a hardcoded Discord webhook URL in the
DISCORD_WEBHOOK_URL environment variable; remove the hardcoded fallback,
rotate/invalidate the exposed webhook immediately, create a new webhook and
store it only in the repository GitHub Secret named DISCORD_WEBHOOK_URL, and
update the workflow to reference only ${{ secrets.DISCORD_WEBHOOK_URL }} (no
fallback/default value) so the value comes exclusively from Secrets; also
confirm no other files contain the leaked URL and replace any occurrences with
the secret reference.
- Line 58: Remove the hardcoded Discord webhook fallback in the
DISCORD_WEBHOOK_URL environment assignment and rely solely on the GitHub Actions
secret; update the line that sets DISCORD_WEBHOOK_URL so it references only
secrets.DISCORD_WEBHOOK_URL (no "||" fallback or literal URL) and ensure any
other occurrences of the same pattern are similarly changed to prevent embedding
a public webhook.
- Around line 20-25: Avoid directly injecting GitHub context into a shell
command; instead assign and escape those values before use to prevent command
substitution. Replace the inline run assignments for PR_NUMBER, PR_TITLE,
PR_AUTHOR, PR_URL, and REPO_NAME with safe assignments such as exporting them
from the workflow env: block or using escaped assignment inside the run step
like PR_TITLE="$(printf '%s' "${{ github.event.pull_request.title }}")" (and
similarly for PR_AUTHOR, PR_URL, PR_NUMBER, REPO_NAME) so the values are treated
as literal strings and cannot be interpreted as shell code.
🧹 Nitpick comments (3)
.github/workflows/pr-label-notify.yml (3)

13-14: 불필요한 체크아웃 단계입니다.

이 워크플로우는 저장소 파일을 사용하지 않고 Discord 알림만 전송하므로, 체크아웃 단계가 필요하지 않습니다. 제거하면 실행 시간을 단축할 수 있습니다.

🔎 제안하는 수정사항
-      - name: Checkout code
-        uses: actions/checkout@v4
-
       - name: Send Discord notification for PR label

27-53: Discord 임베드 구조가 올바르게 구성되어 있습니다.

Discord API의 임베드 형식에 맞게 잘 작성되어 있으며, PR 정보를 명확하게 표시합니다. 다만 Line 30의 @프론트 멘션을 환경 변수나 설정으로 관리하면 더 유연해질 수 있습니다.


60-64: 메시지에 특수 문자가 포함되면 JSON 구문 오류가 발생할 수 있습니다.

MESSAGE 변수에 큰따옴표나 개행 문자가 포함되면 JSON이 깨질 수 있습니다. jq를 사용하여 안전하게 JSON을 생성하는 것을 권장합니다.

🔎 제안하는 수정사항
       - name: Send Discord notification for webhook
         if: github.event_name == 'repository_dispatch'
         env:
           DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
+          MESSAGE: ${{ github.event.client_payload.message || '리뷰가 필요합니다! @프론트' }}
         run: |
-          MESSAGE="${{ github.event.client_payload.message || '리뷰가 필요합니다! @프론트' }}"
-
-          curl -X POST "$DISCORD_WEBHOOK_URL" \
+          jq -n \
+            --arg content "$MESSAGE" \
+            '{content: $content}' \
+          | curl -X POST "$DISCORD_WEBHOOK_URL" \
             -H "Content-Type: application/json" \
-            -d "{\"content\": \"$MESSAGE\"}"
+            -d @-
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03026c7 and 492f80c.

📒 Files selected for processing (5)
  • .github/workflows/pr-label-notify.yml
  • lint-fix.prd.md
  • solid-connect-web@2.2445
  • tsc
  • 클로드.md
💤 Files with no reviewable changes (1)
  • lint-fix.prd.md
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 242
File: src/components/ui/TabSelector.tsx:10-11
Timestamp: 2025-08-12T09:41:44.182Z
Learning: manNomi prefers to keep reusable UI components simple and focused on core functionality rather than adding many features. They don't want to over-engineer flexible/reusable UI components at the initial stage.
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 245
File: src/components/mentor/MentorChatCard/index.tsx:17-21
Timestamp: 2025-08-24T11:14:34.297Z
Learning: manNomi prefers not to receive accessibility suggestions or recommendations during code reviews.
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 245
File: src/api/auth/client/usePostLogout.ts:17-33
Timestamp: 2025-08-24T11:13:08.477Z
Learning: manNomi prefers to prioritize user experience over perfect state consistency in auth flows. Specifically, in logout scenarios, they prefer to keep tokens intact on API failure to avoid forcing users to re-login, even if it means temporary UI state inconsistency.
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 245
File: src/api/auth/client/useDeleteUserAccount.ts:17-27
Timestamp: 2025-08-24T11:11:40.758Z
Learning: manNomi prefers optimistic navigation in auth-related flows (like account deletion) to prevent race conditions where token clearing before navigation could cause intermediate redirects to login page due to pending async requests failing.
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 242
File: src/types/mentor.ts:70-73
Timestamp: 2025-08-12T04:07:04.134Z
Learning: manNomi prefers using Korean labels directly in enum values (e.g., MentorTab.MY_MENTEE = "나의 멘티") over separating enum keys from UI labels for efficiency and intuitiveness, considering scalability concerns as excessive for their current project needs.
🪛 actionlint (1.7.9)
.github/workflows/pr-label-notify.yml

20-20: "github.event.pull_request.title" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/reference/security/secure-use#good-practices-for-mitigating-script-injection-attacks for more details

(expression)

🔇 Additional comments (4)
클로드.md (4)

1-8: 커밋 규칙이 명확하고 잘 정리되어 있습니다.

이모지 사용, 원자적 커밋, 간결한 메시지 작성이라는 세 가지 핵심 원칙이 간결하게 잘 표현되어 있습니다.


9-30: 이모지 가이드가 포괄적이고 실용적입니다.

17개의 이모지가 일반적인 커밋 시나리오를 모두 커버하고 있어 팀원들이 적절한 이모지를 쉽게 선택할 수 있습니다.


31-46: 예시가 명확하고 교육적입니다.

좋은 예와 나쁜 예를 통해 커밋 메시지 작성 규칙이 직관적으로 이해되도록 구성되어 있습니다.


48-56: 원자적 커밋 가이드가 명확합니다.

커밋을 논리적 단위로 분리하는 기준이 구체적으로 제시되어 있어 팀원들이 실천하기 쉽습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Fix all issues with AI Agents 🤖
In @.github/workflows/pr-label-notify.yml:
- Around line 64-76: The MESSAGE variable is assigned directly from
github.event.client_payload.message and injected into a JSON string, allowing
script injection; stop building the JSON with manual shell string interpolation
and instead construct the payload safely with jq (e.g., pass the incoming
message into jq via --arg and let jq produce the JSON), then feed jq's output to
curl (curl -d @-), ensuring you no longer interpolate "$MESSAGE" into the
single-quoted JSON body and you keep the allowed_mentions structure created by
jq.
♻️ Duplicate comments (3)
.github/workflows/pr-label-notify.yml (3)

19-19: 하드코딩된 Discord 웹훅 URL을 즉시 제거해야 합니다.

이전 리뷰에서 지적된 보안 취약점이 여전히 수정되지 않았습니다. 노출된 웹훅 URL은 누구나 해당 Discord 채널에 메시지를 전송할 수 있게 하므로, 폴백 값을 완전히 제거하고 GitHub Secrets만 사용해야 합니다.

🔎 제안하는 수정사항
-          DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL || 'https://discord.com/api/webhooks/1457757557438550177/8WvnhSLYFfxGRpsDD_ExCONT41dNKhpxw78D6m66nxEkwVMsuTdXifHQXm0JT4Z7dNp2' }}
+          DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}

20-58: 스크립트 인젝션 취약점을 수정해야 합니다.

이전 리뷰에서 지적된 보안 취약점이 여전히 수정되지 않았습니다. PR 제목, 작성자명 등의 신뢰할 수 없는 입력값을 쉘 스크립트와 JSON 페이로드에서 직접 사용하면 악의적인 코드 실행이 가능합니다.

더 나아가, 단순히 환경 변수로 이동하는 것만으로는 불충분합니다. JSON 문자열 내에서 변수를 직접 삽입할 때(예: line 34, 41, 46) 적절한 이스케이핑 없이는 여전히 인젝션 공격에 취약합니다.

🔎 제안하는 안전한 수정사항

jq를 사용하여 JSON을 안전하게 생성하세요:

      - name: Send Discord notification for PR label
        if: github.event_name == 'pull_request' && github.event.label.name == 'need_review'
        env:
          DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
+          PR_NUMBER: ${{ github.event.pull_request.number }}
+          PR_TITLE: ${{ github.event.pull_request.title }}
+          PR_AUTHOR: ${{ github.event.pull_request.user.login }}
+          PR_URL: ${{ github.event.pull_request.html_url }}
+          REPO_NAME: ${{ github.repository }}
+          DISCORD_ROLE_ID: ${{ secrets.DISCORD_ROLE_ID || '1368737911301865503' }}
        run: |
-          PR_NUMBER="${{ github.event.pull_request.number }}"
-          PR_TITLE="${{ github.event.pull_request.title }}"
-          PR_AUTHOR="${{ github.event.pull_request.user.login }}"
-          PR_URL="${{ github.event.pull_request.html_url }}"
-          REPO_NAME="${{ github.repository }}"
-
-          curl -X POST "$DISCORD_WEBHOOK_URL" \
+          TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
+          
+          PAYLOAD=$(jq -n \
+            --arg username "프론트 PR 리뷰봇" \
+            --arg avatar_url "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png" \
+            --arg content "리뷰가 필요합니다! <@&$DISCORD_ROLE_ID>" \
+            --arg pr_number "$PR_NUMBER" \
+            --arg pr_title "$PR_TITLE" \
+            --arg pr_url "$PR_URL" \
+            --arg pr_author "$PR_AUTHOR" \
+            --arg repo_name "$REPO_NAME" \
+            --arg timestamp "$TIMESTAMP" \
+            --arg role_id "$DISCORD_ROLE_ID" \
+            '{
+              username: $username,
+              avatar_url: $avatar_url,
+              content: $content,
+              embeds: [{
+                title: ("PR #" + $pr_number + ": " + $pr_title),
+                description: "리뷰 요청이 있습니다",
+                url: $pr_url,
+                color: 3447003,
+                fields: [
+                  {
+                    name: "작성자",
+                    value: $pr_author,
+                    inline: true
+                  },
+                  {
+                    name: "저장소",
+                    value: $repo_name,
+                    inline: true
+                  }
+                ],
+                footer: {
+                  text: "GitHub Actions"
+                },
+                timestamp: $timestamp
+              }],
+              allowed_mentions: {
+                roles: [$role_id]
+              }
+            }')
+          
+          curl -X POST "$DISCORD_WEBHOOK_URL" \
             -H "Content-Type: application/json" \
-            -d '{
-              "username": "프론트 PR 리뷰봇",
-              "avatar_url": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
-              "content": "리뷰가 필요합니다! <@&1368737911301865503>",
-              "embeds": [{
-                "title": "PR #'"$PR_NUMBER"': '"$PR_TITLE"'",
-                "description": "리뷰 요청이 있습니다",
-                "url": "'"$PR_URL"'",
-                "color": 3447003,
-                "fields": [
-                  {
-                    "name": "작성자",
-                    "value": "'"$PR_AUTHOR"'",
-                    "inline": true
-                  },
-                  {
-                    "name": "저장소",
-                    "value": "'"$REPO_NAME"'",
-                    "inline": true
-                  }
-                ],
-                "footer": {
-                  "text": "GitHub Actions"
-                },
-                "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
-              }],
-              "allowed_mentions": {
-                "roles": ["1368737911301865503"]
-              }
-            }'
+            -d "$PAYLOAD"

63-63: 하드코딩된 Discord 웹훅 URL을 제거해야 합니다.

Line 19와 동일한 보안 취약점이 여기에도 존재합니다. 하드코딩된 폴백 URL을 제거하고 GitHub Secrets만 사용해야 합니다.

🔎 제안하는 수정사항
-          DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL || 'https://discord.com/api/webhooks/1457757557438550177/8WvnhSLYFfxGRpsDD_ExCONT41dNKhpxw78D6m66nxEkwVMsuTdXifHQXm0JT4Z7dNp2' }}
+          DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c79ab76 and 55fa6f5.

📒 Files selected for processing (1)
  • .github/workflows/pr-label-notify.yml
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 242
File: src/components/ui/TabSelector.tsx:10-11
Timestamp: 2025-08-12T09:41:44.182Z
Learning: manNomi prefers to keep reusable UI components simple and focused on core functionality rather than adding many features. They don't want to over-engineer flexible/reusable UI components at the initial stage.
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 245
File: src/components/mentor/MentorChatCard/index.tsx:17-21
Timestamp: 2025-08-24T11:14:34.297Z
Learning: manNomi prefers not to receive accessibility suggestions or recommendations during code reviews.
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 245
File: src/api/auth/client/usePostLogout.ts:17-33
Timestamp: 2025-08-24T11:13:08.477Z
Learning: manNomi prefers to prioritize user experience over perfect state consistency in auth flows. Specifically, in logout scenarios, they prefer to keep tokens intact on API failure to avoid forcing users to re-login, even if it means temporary UI state inconsistency.
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 245
File: src/api/auth/client/useDeleteUserAccount.ts:17-27
Timestamp: 2025-08-24T11:11:40.758Z
Learning: manNomi prefers optimistic navigation in auth-related flows (like account deletion) to prevent race conditions where token clearing before navigation could cause intermediate redirects to login page due to pending async requests failing.
Learnt from: manNomi
Repo: solid-connection/solid-connect-web PR: 242
File: src/types/mentor.ts:70-73
Timestamp: 2025-08-12T04:07:04.134Z
Learning: manNomi prefers using Korean labels directly in enum values (e.g., MentorTab.MY_MENTEE = "나의 멘티") over separating enum keys from UI labels for efficiency and intuitiveness, considering scalability concerns as excessive for their current project needs.
🪛 actionlint (1.7.9)
.github/workflows/pr-label-notify.yml

20-20: "github.event.pull_request.title" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/reference/security/secure-use#good-practices-for-mitigating-script-injection-attacks for more details

(expression)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build
🔇 Additional comments (1)
.github/workflows/pr-label-notify.yml (1)

1-14: 워크플로우 구조가 적절합니다.

PR 라벨 이벤트와 repository_dispatch를 감지하는 트리거 설정이 올바르게 구성되어 있습니다.

- fork PR에서 secrets 접근 가능하도록 pull_request_target 사용
- CODEOWNERS만 Discord 알림을 트리거할 수 있도록 보안 체크 추가
- CODEOWNERS에 enunsnv, khwww 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@manNomi manNomi merged commit 544366a into solid-connection:main Jan 5, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant