Skip to content

๐Ÿ›ก๏ธ [CRITICAL] ๊ด€๋ฆฌ์ž ์•„์ด๋””ยท๋น„๋ฐ€๋ฒˆํ˜ธ ํ•˜๋“œ์ฝ”๋”ฉ ์ž๊ฒฉ์ฆ๋ช… ์™„์ „ ์ œ๊ฑฐ#7

Closed
seonghobae wants to merge 14 commits into
mainfrom
fix/hardcoded-admin-credentials-8054597278288833568
Closed

Conversation

@seonghobae

@seonghobae seonghobae commented May 29, 2026

Copy link
Copy Markdown

๐Ÿšจ ์‹ฌ๊ฐ๋„: CRITICAL

์ทจ์•ฝ์  ์„ค๋ช…

packages/web/src/lib/server/admin-auth.ts์— ADMIN_USERNAME๊ณผ ADMIN_PASSWORD ๋‘ ์ž๊ฒฉ์ฆ๋ช…์ด ๋ชจ๋‘ ์†Œ์Šค ์ฝ”๋“œ์— ์ •์ ์œผ๋กœ ํ•˜๋“œ์ฝ”๋”ฉ๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

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

์ €์žฅ์†Œ ์ฝ๊ธฐ ๊ถŒํ•œ๋งŒ ์žˆ์–ด๋„ ๊ด€๋ฆฌ์ž ์•„์ด๋””ยท๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๊ทธ๋Œ€๋กœ ํš๋“ํ•˜์—ฌ ์ธ์ฆ ์—†์ด ์‹œ์Šคํ…œ ์ „์ฒด๋ฅผ ์žฅ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PR #3๊ณผ์˜ ์ฐจ์ด์ 

PR #3์€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋งŒ ์ˆ˜์ •ํ–ˆ์œผ๋‚˜, ์ด PR์€ ๊ด€๋ฆฌ์ž ์•„์ด๋””(ADMIN_USERNAME)๊นŒ์ง€ ํฌํ•จํ•œ ๋ชจ๋“  ์ž๊ฒฉ์ฆ๋ช…์„ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์ด์ „ํ•ฉ๋‹ˆ๋‹ค.

์ˆ˜์ • ๋‚ด์šฉ

ํŒŒ์ผ ๋ณ€๊ฒฝ ์‚ฌํ•ญ
packages/web/src/lib/server/admin-auth.ts ํ•˜๋“œ์ฝ”๋”ฉ๋œ usernameยทpassword โ†’ env.ADMIN_USERNAME / env.ADMIN_PASSWORD
packages/web/src/lib/server/env.ts ADMIN_USERNAME, ADMIN_PASSWORD zod ์Šคํ‚ค๋งˆ ์ถ”๊ฐ€
packages/web/.env.example ๋‘ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์˜ˆ์‹œ ์ถ”๊ฐ€
.github/workflows/ci.yml CI ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ฒ€์ฆ ๊ฐ•ํ™”

๋ฐฐํฌ ์ „ ํ•„์ˆ˜ ์กฐ์น˜

# .env ๋˜๋Š” ํ˜ธ์ŠคํŒ… ํ”Œ๋žซํผ ํ™˜๊ฒฝ๋ณ€์ˆ˜์— ์•„๋ž˜ ์ถ”๊ฐ€
ADMIN_USERNAME=your-secure-username
ADMIN_PASSWORD=your-secure-password

โš ๏ธ ๊ธฐ์กด์— ๋…ธ์ถœ๋œ ์ž๊ฒฉ์ฆ๋ช…์„ ์‚ฌ์šฉ ์ค‘์ด๋ผ๋ฉด ์ฆ‰์‹œ ๋ณ€๊ฒฝํ•˜์‹ญ์‹œ์˜ค.

@google-labs-jules

Copy link
Copy Markdown

๐Ÿ‘‹ Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a ๐Ÿ‘€ emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@seonghobae, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 3 minutes and 39 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

โŒ› How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

๐Ÿšฆ How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

โ„น๏ธ Review info
โš™๏ธ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6aba842d-c0cd-4303-a9e1-b67f2fa003c5

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 982d2de and bef3156.

๐Ÿ“’ Files selected for processing (3)
  • .gitignore
  • packages/web/src/lib/server/admin-auth.ts
  • packages/web/src/lib/server/env.ts
๐Ÿ“ Walkthrough

์›Œํฌ์Šค๋ฃจ

ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช…(ADMIN_USERNAME, ADMIN_PASSWORD)์„ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์ด๋™ํ•˜๊ณ  EnvSchema ๊ฒ€์ฆ์„ ์ถ”๊ฐ€ํ–ˆ์œผ๋ฉฐ, ๊ด€๋ฆฌ์ž ์ธ์ฆ ๋น„๊ต ๋กœ์ง์„ PBKDF2 ๊ธฐ๋ฐ˜ ํŒŒ์ƒ ํ‚ค์™€ timingSafeEqual๋ฅผ ์ด์šฉํ•ด ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค. CI, .env ์˜ˆ์‹œ, ๋ณด์•ˆ ์„ผํ‹ฐ๋„ ๋ฌธ์„œ๋„ ํ•จ๊ป˜ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ์‚ฌํ•ญ

๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช… ํ™˜๊ฒฝ๋ณ€์ˆ˜ํ™”

Layer / File(s) ์š”์•ฝ
ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ์ถ”๊ฐ€
packages/web/src/lib/server/env.ts
EnvSchema์— ADMIN_USERNAME๊ณผ ADMIN_PASSWORD ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์กด์žฌ์„ฑ๊ณผ ์ตœ์†Œ ๊ธธ์ด๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
๊ด€๋ฆฌ์ž ์ธ์ฆ ๊ตฌํ˜„ ๋ฐ ๋น„๊ต ๋ฐฉ์‹ ๋ณ€๊ฒฝ
packages/web/src/lib/server/admin-auth.ts
ํ•˜๋“œ์ฝ”๋”ฉ๋œ ADMIN_USERNAME/ADMIN_PASSWORD๋ฅผ env๋กœ ๋Œ€์ฒดํ•˜๊ณ , ๋น„๊ต ์œ ํ‹ธ์„ ์žฌ๊ตฌ์„ฑํ•˜์—ฌ ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” PBKDF2๋กœ ํŒŒ์ƒ ํ‚ค๋ฅผ ๋งŒ๋“ค๊ณ  timingSafeEqual๋กœ ๋น„๊ตํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค. username ๋ฐ ์„ธ์…˜/์ž„ํผ์†Œ๋„ค์ด์…˜ ํ† ํฐ์˜ ์„œ๋ช…/ํ”„๋ฆฌํ”ฝ์Šค ๋น„๊ต๋„ timing-safe ๋ฐฉ์‹์œผ๋กœ ๋ฐ”๋€Œ์—ˆ์Šต๋‹ˆ๋‹ค.
ํ™˜๊ฒฝ ์„ค์ •, CI ์›Œํฌํ”Œ๋กœ์šฐ, ๋ณด์•ˆ ๋ฌธ์„œ
packages/web/.env.example, .github/workflows/ci.yml, .jules/sentinel.md
.env.example์— ๊ด€๋ฆฌ์ž ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์˜ˆ์‹œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , CI build ์ž‘์—… env์— ADMIN_USERNAME/ADMIN_PASSWORD๋ฅผ ์ถ”๊ฐ€ํ–ˆ์œผ๋ฉฐ ๋ณด์•ˆ ์„ผํ‹ฐ๋„์— ํ•˜๋“œ์ฝ”๋”ฉ ์ด์Šˆ ๋ฐ ๊ถŒ์žฅ์‚ฌํ•ญ์„ ๊ธฐ๋กํ–ˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์ƒ ์ฝ”๋“œ ๋ฆฌ๋ทฐ ๋…ธ๋ ฅ

๐ŸŽฏ 4 (Complex) | โฑ๏ธ ~45 minutes

์‹œ

๊ด€๋ฆฌ์ž ๋น„๋ฐ€์€ ์ˆฒ์— ์ˆจ๊ธฐ๊ณ ,
ํ† ๋ผ ๊ท€๋กœ ์†์‚ญ์ด๋ฉฐ ์˜ฎ๊ฒผ๋„ค.
๊ฒ€์ฆํ•˜๊ณ  ๊ธธ์ด ์žฌ์–ด ๋น„๊ตํ•˜๋‹ˆ,
์•ˆ์ „ํ•œ ๋ฐคํ•˜๋Š˜ ๋น›๋‚˜๋ฆฌ๋ผ.
๐Ÿ‡โœจ


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

โŒ Failed checks (1 error)

Check name Status Explanation Resolution
Docstring Coverage โŒ Error Docstring coverage is 0.00% which is insufficient. The required threshold is 100.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
โœ… Passed checks (4 passed)
Check name Status Explanation
Linked Issues check โœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check โœ… Passed Check skipped because no linked issues were found for this pull request.
Title check โœ… Passed PR ์ œ๋ชฉ์ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์˜ ํ•ต์‹ฌ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ฐ˜์˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช… ์ œ๊ฑฐ๋ผ๋Š” ์ฃผ์š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ •ํ™•ํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
Description check โœ… Passed PR ์„ค๋ช…์ด ์ทจ์•ฝ์ , ์˜ํ–ฅ ๋ฒ”์œ„, ์ˆ˜์ • ๋‚ด์šฉ, ๋ฐฐํฌ ์ „ ํ•„์ˆ˜ ์กฐ์น˜๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ธฐ์ˆ ํ•˜๋ฉฐ ๋ณ€๊ฒฝ์‚ฌํ•ญ๊ณผ ์ง์ ‘ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
โœจ Finishing Touches
๐Ÿงช Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/hardcoded-admin-credentials-8054597278288833568
โœจ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/hardcoded-admin-credentials-8054597278288833568

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


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

Comment thread packages/web/src/lib/server/admin-auth.ts Fixed
Comment thread packages/web/src/lib/server/admin-auth.ts Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

๐Ÿค– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.jules/sentinel.md:
- Line 1: Update the document header date in the first line: replace the
hardcoded string "## 2024-05-29 - [CRITICAL] Fix hardcoded admin credentials"
with the correct change date "## 2026-05-29 - [CRITICAL] Fix hardcoded admin
credentials" (i.e., update the date portion of that header line to match the
actual change timestamp).

In `@packages/web/src/lib/server/env.ts`:
- Around line 8-9: The current env schema allows ADMIN_USERNAME to contain dots
(breaking session cookie parsing) and sets ADMIN_PASSWORD to min(1), which is
too weak; update the schema for ADMIN_USERNAME to disallow '.' and whitespace
(e.g., use a regex that forbids '.' and spaces) and tighten ADMIN_PASSWORD to a
stronger policy (e.g., minimum length 12 and a regex requiring at least one
uppercase, one lowercase, one digit, and one special character and no
leading/trailing whitespace) so validation in the ADMIN_USERNAME and
ADMIN_PASSWORD z.string() entries rejects unsafe values and enforces a robust
admin password policy.
๐Ÿช„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

โ„น๏ธ Review info
โš™๏ธ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 816796e2-f152-4ca8-b301-7eeee9049595

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 8640510 and 96322ae.

๐Ÿ“’ Files selected for processing (5)
  • .github/workflows/ci.yml
  • .jules/sentinel.md
  • packages/web/.env.example
  • packages/web/src/lib/server/admin-auth.ts
  • packages/web/src/lib/server/env.ts

Comment thread .jules/sentinel.md Outdated
@@ -0,0 +1,4 @@
## 2024-05-29 - [CRITICAL] Fix hardcoded admin credentials

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸก Minor | โšก Quick win

๋ฌธ์„œ ๋‚ ์งœ๋ฅผ ์‹ค์ œ ๋ณ€๊ฒฝ ์‹œ์ ์œผ๋กœ ๋งž์ถฐ ์ฃผ์„ธ์š”.

Line 1์˜ 2024-05-29๋Š” ์ด๋ฒˆ ๋ณ€๊ฒฝ ๋งฅ๋ฝ(2026๋…„ 5์›” 29์ผ)๊ณผ ๋งž์ง€ ์•Š์•„ ์ด๋ ฅ ์ถ”์  ์‹œ ํ˜ผ์„ ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ œ์•ˆ ํŒจ์น˜
-## 2024-05-29 - [CRITICAL] Fix hardcoded admin credentials
+## 2026-05-29 - [CRITICAL] Fix hardcoded admin credentials
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## 2024-05-29 - [CRITICAL] Fix hardcoded admin credentials
## 2026-05-29 - [CRITICAL] Fix hardcoded admin credentials
๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.jules/sentinel.md at line 1, Update the document header date in the first
line: replace the hardcoded string "## 2024-05-29 - [CRITICAL] Fix hardcoded
admin credentials" with the correct change date "## 2026-05-29 - [CRITICAL] Fix
hardcoded admin credentials" (i.e., update the date portion of that header line
to match the actual change timestamp).

Comment thread packages/web/src/lib/server/env.ts Outdated
Comment on lines +8 to +9
ADMIN_USERNAME: z.string().min(1),
ADMIN_PASSWORD: z.string().min(1),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major | โšก Quick win

ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์Šคํ‚ค๋งˆ ์ œ์•ฝ์ด ๋„ˆ๋ฌด ์•ฝํ•ฉ๋‹ˆ๋‹ค.

Line 8์€ .์„ ํ—ˆ์šฉํ•ด ์„ธ์…˜ ์ฟ ํ‚ค ํŒŒ์‹ฑ(split('.'))์„ ๊นจ๋œจ๋ฆด ์ˆ˜ ์žˆ๊ณ , Line 9์˜ min(1)์€ ๊ด€๋ฆฌ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ ์ •์ฑ…์œผ๋กœ ๋„ˆ๋ฌด ์•ฝํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐํฌ ์‹œ ๊ด€๋ฆฌ์ž ๋กœ๊ทธ์ธ ์žฅ์• /๋ณด์•ˆ ์ €ํ•˜๋ฅผ ๋ง‰๊ธฐ ์œ„ํ•ด ์Šคํ‚ค๋งˆ๋ฅผ ๋” ์—„๊ฒฉํžˆ ์ œํ•œํ•ด ์ฃผ์„ธ์š”.

์ œ์•ˆ ํŒจ์น˜
 const EnvSchema = z.object({
   DATABASE_URL: z.string().min(1),
   DIRECT_URL: z.string().min(1),
   JWT_SECRET: z.string().min(32),
-  ADMIN_USERNAME: z.string().min(1),
-  ADMIN_PASSWORD: z.string().min(1),
+  ADMIN_USERNAME: z
+    .string()
+    .min(3)
+    .regex(/^[A-Za-z0-9_-]+$/, 'ADMIN_USERNAME must not contain "." or spaces'),
+  ADMIN_PASSWORD: z.string().min(12),
 })
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ADMIN_USERNAME: z.string().min(1),
ADMIN_PASSWORD: z.string().min(1),
ADMIN_USERNAME: z
.string()
.min(3)
.regex(/^[A-Za-z0-9_-]+$/, 'ADMIN_USERNAME must not contain "." or spaces'),
ADMIN_PASSWORD: z.string().min(12),
๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/lib/server/env.ts` around lines 8 - 9, The current env
schema allows ADMIN_USERNAME to contain dots (breaking session cookie parsing)
and sets ADMIN_PASSWORD to min(1), which is too weak; update the schema for
ADMIN_USERNAME to disallow '.' and whitespace (e.g., use a regex that forbids
'.' and spaces) and tighten ADMIN_PASSWORD to a stronger policy (e.g., minimum
length 12 and a regex requiring at least one uppercase, one lowercase, one
digit, and one special character and no leading/trailing whitespace) so
validation in the ADMIN_USERNAME and ADMIN_PASSWORD z.string() entries rejects
unsafe values and enforces a robust admin password policy.

@seonghobae

Copy link
Copy Markdown
Author

@codex[agent] ๋ฆฌ๋ทฐํ•˜์‹œ์˜ค.

@google-labs-jules

Copy link
Copy Markdown

@codex[agent] ๋ฆฌ๋ทฐํ•˜์‹œ์˜ค.

Acknowledged.

Co-authored-by: seonghobae <8172694+seonghobae@users.noreply.github.com>
@Codex

Codex AI commented May 30, 2026

Copy link
Copy Markdown

@codex[agent] ๋ฆฌ๋ทฐํ•˜์‹œ์˜ค.

๋ฆฌ๋ทฐ ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. packages/web/src/lib/server/admin-auth.ts์—์„œ CodeQL๊ฐ€ ์ง€์ ํ•˜๋˜ SHA256 ๊ธฐ๋ฐ˜ ํ•ด์‹œ ๋น„๊ต๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  timingSafeEqual ๊ธฐ๋ฐ˜ ๋ฌธ์ž์—ด ๋น„๊ต๋กœ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค. packages/web lint/typecheck/test๋„ ํ†ต๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. Commit: 4aa0a93

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • checkpoint.prisma.io
    • Triggering command: /opt/hostedtoolcache/node/24.16.0/x64/bin/node /opt/hostedtoolcache/node/24.16.0/x64/bin/node /home/REDACTED/work/argos/argos/node_modules/.pnpm/prisma@6.19.3_typescript@5.9.3/node_modules/prisma/build/child {&#34;product&#34;:&#34;prisma&#34;,&#34;version&#34;:&#34;6.19.3&#34;,&#34;cli_install_type&#34;:&#34;local&#34;,&#34;information&#34;:&#34;&#34;,&#34;local_timestamp&#34;:&#34;2026-05-30T14:42:57Z&#34;,&#34;project_hash&#34;:&#34;256f53da&#34;,&#34;cli_path&#34;:&#34;/home/REDACTED/work/argos/argos/packages/web/node_modules/prisma/build/index.js&#34;,&#34;cli_path_hash (dns block)
  • fonts.googleapis.com
    • Triggering command: /opt/hostedtoolcache/node/24.16.0/x64/bin/node /opt/hostedtoolcache/node/24.16.0/x64/bin/node /home/REDACTED/work/argos/argos/node_modules/.pnpm/next@15.5.15_@babel&#43;core@7.29.0_react-dom@19.2.5_react@19.2.5__react@19.2.5/node_modules/next/dist/compiled/jest-worker/processChild.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@seonghobae

Copy link
Copy Markdown
Author

@codex[agent] ์ด ๋ณด์•ˆ ์ˆ˜์ • PR์„ ๊ฒ€ํ† ํ•ด ์ฃผ์„ธ์š”:

  1. ๋‘ ์ž๊ฒฉ์ฆ๋ช…(ADMIN_USERNAME, ADMIN_PASSWORD) ๋ชจ๋‘ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์™„์ „ํžˆ ์ด์ „๋˜์—ˆ๋Š”์ง€
  2. PR #3๊ณผ ์ฝ”๋“œ ์ถฉ๋Œ ๋˜๋Š” ์ค‘๋ณต ์ ์šฉ ๊ฐ€๋Šฅ์„ฑ ๊ฒ€ํ† 
  3. admin-auth.ts์˜ ์ธ์ฆ ๋กœ์ง์— ํƒ€์ด๋ฐ ์–ดํƒ ์ทจ์•ฝ์ (์ƒ์ˆ˜ ์‹œ๊ฐ„ ๋น„๊ต ๋ฏธ์ ์šฉ)์ด ์—†๋Š”์ง€

@google-labs-jules

Copy link
Copy Markdown

@codex[agent] ์ด ๋ณด์•ˆ ์ˆ˜์ • PR์„ ๊ฒ€ํ† ํ•ด ์ฃผ์„ธ์š”:

  1. ๋‘ ์ž๊ฒฉ์ฆ๋ช…(ADMIN_USERNAME, ADMIN_PASSWORD) ๋ชจ๋‘ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์™„์ „ํžˆ ์ด์ „๋˜์—ˆ๋Š”์ง€
  2. PR #3๊ณผ ์ฝ”๋“œ ์ถฉ๋Œ ๋˜๋Š” ์ค‘๋ณต ์ ์šฉ ๊ฐ€๋Šฅ์„ฑ ๊ฒ€ํ† 
  3. admin-auth.ts์˜ ์ธ์ฆ ๋กœ์ง์— ํƒ€์ด๋ฐ ์–ดํƒ ์ทจ์•ฝ์ (์ƒ์ˆ˜ ์‹œ๊ฐ„ ๋น„๊ต ๋ฏธ์ ์šฉ)์ด ์—†๋Š”์ง€

Acknowledged.

seonghobae and others added 3 commits May 30, 2026 15:42
Co-authored-by: seonghobae <8172694+seonghobae@users.noreply.github.com>
Co-authored-by: seonghobae <8172694+seonghobae@users.noreply.github.com>
@Codex

Codex AI commented May 30, 2026

Copy link
Copy Markdown

@codex[agent] ์ด ๋ณด์•ˆ ์ˆ˜์ • PR์„ ๊ฒ€ํ† ํ•ด ์ฃผ์„ธ์š”:

  1. ๋‘ ์ž๊ฒฉ์ฆ๋ช…(ADMIN_USERNAME, ADMIN_PASSWORD) ๋ชจ๋‘ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์™„์ „ํžˆ ์ด์ „๋˜์—ˆ๋Š”์ง€
  2. PR #3๊ณผ ์ฝ”๋“œ ์ถฉ๋Œ ๋˜๋Š” ...
  1. ํ˜„์žฌ PR ๊ธฐ์ค€์œผ๋กœ ADMIN_USERNAME, ADMIN_PASSWORD๋Š” ๋ชจ๋‘ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์ด์ „๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค: /home/runner/work/argos/argos/packages/web/src/lib/server/env.ts์—์„œ ์Šคํ‚ค๋งˆ๋กœ ๊ฐ•์ œํ•˜๊ณ , /home/runner/work/argos/argos/packages/web/src/lib/server/admin-auth.ts๋Š” env.ADMIN_USERNAME/ADMIN_PASSWORD๋งŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. .env.example์™€ .github/workflows/ci.yml์—๋„ ํ”Œ๋ ˆ์ด์Šคํ™€๋”๊ฐ€ ๋“ค์–ด๊ฐ€ ์žˆ๊ณ , ์ฝ”๋“œ ๋‚ด ํ•˜๋“œ์ฝ”๋”ฉ์€ ๋” ์ด์ƒ ๊ฒ€์ƒ‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  2. PR #3๋Š” ๋™์ผ ์ทจ์ง€์˜ ์ค‘๋ณต ์ˆ˜์ •(๊ฐ™์€ ํŒŒ์ผ๋“ค ์ˆ˜์ •)์ด๋ผ ๋ณ‘ํ•ฉ ์‹œ ์ถฉ๋Œ/์ค‘๋ณต ์ ์šฉ ๊ฐ€๋Šฅ์„ฑ์ด ํฝ๋‹ˆ๋‹ค. PR #3๋Š” ADMIN_SECRET(๋‹จ์ผ ๋น„๋ฐ€)๋กœ ๋ฐ”๊พธ๊ณ  ADMIN_USERNAME์„ ํ•˜๋“œ์ฝ”๋”ฉ('admin')ํ•˜๋Š” ๋ฐฉํ–ฅ์ด๋ผ, ํ˜„์žฌ PR์˜ ADMIN_USERNAME/ADMIN_PASSWORD ๋ฐฉ์‹๊ณผ ๋ณ€์ˆ˜๋ช…์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋‘˜ ์ค‘ ํ•˜๋‚˜์˜ ์ ‘๊ทผ์œผ๋กœ ์ •๋ฆฌ(ํ•˜๋‚˜๋ฅผ closeํ•˜๊ฑฐ๋‚˜, ํ•˜๋‚˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ rebase/์ˆ˜์ •)ํ•˜๋Š” ๊ฒŒ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

  3. admin-auth.ts ๋น„๊ต ๋กœ์ง์€ ์ƒ์ˆ˜์‹œ๊ฐ„ ๋น„๊ต๋กœ ๊ฐ•ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋ช…/์ฟ ํ‚ค ์„œ๋ช…/ํ”„๋ฆฌํ”ฝ์Šค๋Š” timingSafeEqual ๊ธฐ๋ฐ˜ safeTimingEqual์„ ์‚ฌ์šฉํ•˜๊ณ , ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” pbkdf2Sync๋กœ ํŒŒ์ƒํ‚ค(๊ณ ์ • ๊ธธ์ด)๋ฅผ ๋งŒ๋“  ๋’ค timingSafeEqual๋กœ ๋น„๊ตํ•ด ํƒ€์ด๋ฐ ์–ดํƒ(๋ฐ ๋น ๋ฅธ brute force) ์œ„ํ—˜์„ ์ค„์˜€์Šต๋‹ˆ๋‹ค. Commit: d75a4e8, 982d2de

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and canโ€™t be posted inline due to platform limitations.

โš ๏ธ Outside diff range comments (1)
packages/web/src/lib/server/admin-auth.ts (1)

10-11: โš ๏ธ Potential issue | ๐ŸŸ  Major | โšก Quick win

ADMIN_USERNAME ๊ตฌ๋ถ„์ž ์•ˆ์ •์„ฑ ๊ฒ€์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Line 10-11์—์„œ ADMIN_USERNAME์ด . ํฌํ•จ ์‹œ, Line 72/96์˜ ์ (.) ๊ธฐ๋ฐ˜ ํŒŒ์‹ฑ ๊ณ„์•ฝ๊ณผ ์ถฉ๋Œํ•ด์„œ ์„ธ์…˜ ์ฟ ํ‚ค/ํ† ํฐ ๊ฒ€์ฆ์ด ์‹คํŒจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“ˆ ์ดˆ๊ธฐํ™” ์‹œ ํ˜•์‹์„ ๊ฐ•์ œํ•˜๊ฑฐ๋‚˜(์˜ˆ: . ๊ธˆ์ง€) ์ธ์ฝ”๋”ฉ๋œ ํ•„๋“œ๋กœ ์ง๋ ฌํ™”ํ•˜์„ธ์š”.

๐Ÿ”ง ์ œ์•ˆ ํŒจ์น˜
 export const ADMIN_USERNAME = env.ADMIN_USERNAME
 export const ADMIN_PASSWORD = env.ADMIN_PASSWORD
+
+if (ADMIN_USERNAME.includes('.')) {
+  throw new Error('ADMIN_USERNAME must not contain "."')
+}
๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/src/lib/server/admin-auth.ts` around lines 10 - 11, The
ADMIN_USERNAME export can contain '.' which breaks the session/token parsing
that splits on '.'; update the module initialization to either validate and
reject/normalize ADMIN_USERNAME (e.g., throw or replace '.'), or export an
encoded form (e.g., base64 or url-encode) and ensure the rest of the code uses
that encoded constant for cookie/token creation and verification; change the
export of ADMIN_USERNAME (and corresponding usages that build/parse the session
cookie/token) so they use the validated or encoded value consistently, and keep
ADMIN_PASSWORD unchanged.
๐Ÿค– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/web/src/lib/server/admin-auth.ts`:
- Around line 44-52: safePasswordEqual currently uses synchronous pbkdf2Sync
with ADMIN_PASSWORD_KDF_ITERATIONS which blocks the event loop on each login;
replace the sync KDF with the async crypto.pbkdf2 (or offload to a worker) and
make safePasswordEqual return a Promise<boolean>, then update
verifyAdminCredentials to be async and await safePasswordEqual, and propagate
async changes to the POST() handler in route.ts so callers await the
verification; ensure you still compare the derived key against
adminPasswordDerivedKey using timingSafeEqual after deriving the key
asynchronously.
- Around line 30-41: The safeTimingEqual function allocates buffers based on the
larger input length which allows an attacker to send extremely long cookie/token
values and trigger DoS; update safeTimingEqual to first check and immediately
return false if the two input string byte lengths differ OR enforce a strict
upper bound on accepted length (e.g., refuse inputs longer than an explicit
MAX_SIGNATURE_LEN) so you avoid unbounded Buffer.alloc calls; apply this change
where safeTimingEqual is used (verifyAdminSessionCookie and
verifyAdminImpersonationToken) so inputs are validated/rejected before any
padding/allocation occurs.

---

Outside diff comments:
In `@packages/web/src/lib/server/admin-auth.ts`:
- Around line 10-11: The ADMIN_USERNAME export can contain '.' which breaks the
session/token parsing that splits on '.'; update the module initialization to
either validate and reject/normalize ADMIN_USERNAME (e.g., throw or replace
'.'), or export an encoded form (e.g., base64 or url-encode) and ensure the rest
of the code uses that encoded constant for cookie/token creation and
verification; change the export of ADMIN_USERNAME (and corresponding usages that
build/parse the session cookie/token) so they use the validated or encoded value
consistently, and keep ADMIN_PASSWORD unchanged.
๐Ÿช„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

โ„น๏ธ Review info
โš™๏ธ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a09a6d7e-f4cc-4bd9-a8b5-f9cfce0c449c

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 4aa0a93 and 982d2de.

๐Ÿ“’ Files selected for processing (1)
  • packages/web/src/lib/server/admin-auth.ts

Comment thread packages/web/src/lib/server/admin-auth.ts Outdated
Comment thread packages/web/src/lib/server/admin-auth.ts Outdated
@seonghobae

Copy link
Copy Markdown
Author

@coderabbitai review

์ด PR์„ ์ „์ฒด ๊ฒ€ํ† ํ•ด ์ฃผ์„ธ์š”. ํŠนํžˆ ๋‹ค์Œ ์‚ฌํ•ญ์„ ์ค‘์ ์ ์œผ๋กœ ํ™•์ธํ•ด ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค:

  • ์ฝ”๋“œ ์ •ํ™•์„ฑ ๋ฐ ์ž ์žฌ์  ๋ฒ„๊ทธ
  • ๋ณด์•ˆ ์ทจ์•ฝ์  ์—ฌ๋ถ€
  • ์„ฑ๋Šฅ ์˜ํ–ฅ
  • ์ฝ”๋”ฉ ํ‘œ์ค€ ๋ฐ best practice ์ค€์ˆ˜ ์—ฌ๋ถ€

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
๐Ÿงฉ Analysis chain

๐Ÿ Script executed:

#!/bin/bash
set -euo pipefail

echo "=== admin-auth.ts ==="
cat packages/web/src/lib/server/admin-auth.ts

echo ""
echo "=== env.ts ==="
cat packages/web/src/lib/server/env.ts

echo ""
echo "=== .env.example ==="
cat packages/web/.env.example

echo ""
echo "=== ci.yml ==="
cat .github/workflows/ci.yml

echo ""
echo "=== PR `#3` info ==="
gh pr view 3 --json title,body,state,files 2>/dev/null || echo "PR `#3` not accessible or not found"

Length of output: 8318



@seonghobae, ์ „์ฒด ๋ฆฌ๋ทฐ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ์ฃผ์š” ํ•ญ๋ชฉ๋ณ„๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.


1. ์ž๊ฒฉ์ฆ๋ช… ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ด์ „ ์—ฌ๋ถ€ โœ… / โš ๏ธ

ADMIN_USERNAME๊ณผ ADMIN_PASSWORD ๋ชจ๋‘ env.ADMIN_USERNAME / env.ADMIN_PASSWORD๋กœ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ด์ „๋˜์—ˆ์Šต๋‹ˆ๋‹ค. EnvSchema์—์„œ Zod ๊ฒ€์ฆ๋„ ์ ์šฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ ๋ฌธ์ œ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค:

  • z.string().min(1) โ€” ADMIN_PASSWORD ๊ฒ€์ฆ์ด ์ตœ์†Œ 1์ž๋งŒ ์š”๊ตฌํ•ฉ๋‹ˆ๋‹ค. ์ตœ์†Œ 12~16์ž ์ด์ƒ์„ ๊ฐ•์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:
    // env.ts
    ADMIN_PASSWORD: z.string().min(16, 'ADMIN_PASSWORD must be at least 16 characters'),
  • .env.example์—์„œ ADMIN_USERNAME="admin" ์‚ฌ์šฉ โ€” ๊ธฐ๋ณธ ์˜ˆ์‹œ๊ฐ€ "admin" ์ด๋ฏ€๋กœ ๊ณต๊ฒฉ์ž์—๊ฒŒ ์‚ฌ์šฉ์ž๋ช… ํžŒํŠธ๋ฅผ ์ค๋‹ˆ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ๊ต์ฒดํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค:
    ADMIN_USERNAME="replace-with-your-admin-username"
    
  • ADMIN_USERNAME / ADMIN_PASSWORD๊ฐ€ export๋กœ ๋…ธ์ถœ๋จ โ€” ์›์‹œ ์ž๊ฒฉ์ฆ๋ช…์„ ๋‹ค๋ฅธ ๋ชจ๋“ˆ๋กœ ๋‚ด๋ณด๋‚ผ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ADMIN_USERNAME์€ ์„ธ์…˜ ์ฟ ํ‚ค ์ƒ์„ฑ ๋กœ์ง ๋‚ด์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๊ณ , ์™ธ๋ถ€์—์„œ ์ฐธ์กฐํ•˜๋Š” ๊ณณ์ด ์žˆ๋‹ค๋ฉด ๋Œ€์‹  verifyAdminCredentials ๋“ฑ์˜ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฆฌํŒฉํ† ๋งํ•˜๋Š” ๊ฒƒ์ด ๊ถŒ์žฅ๋ฉ๋‹ˆ๋‹ค.

2. PR #3๊ณผ์˜ ์ถฉ๋Œ/์ค‘๋ณต ๊ฐ€๋Šฅ์„ฑ โš ๏ธ

PR #3๋„ ํ˜„์žฌ OPEN ์ƒํƒœ์ด๋ฉฐ, ๊ฐ™์€ ํŒŒ์ผ๋“ค์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค:

ํŒŒ์ผ PR #3 PR #7
packages/web/src/lib/server/admin-auth.ts โœ… ์ˆ˜์ • โœ… ์ˆ˜์ •
packages/web/src/lib/server/env.ts โœ… ์ˆ˜์ • โœ… ์ˆ˜์ •
packages/web/.env.example โœ… ์ˆ˜์ • โœ… ์ˆ˜์ •
.github/workflows/ci.yml โœ… ์ˆ˜์ • โœ… ์ˆ˜์ •
packages/web/src/app/api/admin/login/route.ts โœ… ์ˆ˜์ • โŒ ๋ฏธ์ˆ˜์ •

PR #3์€ ADMIN_PASSWORD๋งŒ ์ด์ „ํ–ˆ๊ณ , PR #7์€ ADMIN_USERNAME๊นŒ์ง€ ์ถ”๊ฐ€๋กœ ์ด์ „ํ–ˆ์Šต๋‹ˆ๋‹ค. PR #7์ด ๋” ์™„์ „ํ•œ ์ˆ˜์ •์ด์ง€๋งŒ, ๋‘ PR์„ ๋™์‹œ์— mergeํ•˜๋ฉด ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. PR #3์„ ๋จผ์ € closeํ•˜๊ณ  PR #7๋งŒ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.


3. ํƒ€์ด๋ฐ ์–ดํƒ ์ทจ์•ฝ์  ๐Ÿ”ด (CRITICAL)

3-1. verifyAdminCredentials์˜ ๋‹จ๋ฝ ํ‰๊ฐ€(Short-circuit) ๋ฌธ์ œ

// ํ˜„์žฌ ์ฝ”๋“œ
export function verifyAdminCredentials(input: { username: string; password: string }): boolean {
  return (
    safeTimingEqual(input.username, ADMIN_USERNAME) &&  // โ† ์—ฌ๊ธฐ์„œ false๋ฉด
    safePasswordEqual(input.password)                    // โ† PBKDF2๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Œ!
  )
}

safeTimingEqual(username ๋น„๊ต, ๋น ๋ฆ„)์ด false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด JavaScript && ๋‹จ๋ฝ ํ‰๊ฐ€๋กœ ์ธํ•ด safePasswordEqual(PBKDF2, ~๋А๋ฆผ)์ด ํ˜ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ณต๊ฒฉ์ž๊ฐ€ ์‘๋‹ต ์‹œ๊ฐ„์„ ์ธก์ •ํ•˜๋ฉด ์˜ฌ๋ฐ”๋ฅธ username ์—ฌ๋ถ€๋ฅผ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ˆ˜์ • ๋ฐฉ๋ฒ•:

export function verifyAdminCredentials(input: { username: string; password: string }): boolean {
  // ๋‘ ๋น„๊ต๋ฅผ ํ•ญ์ƒ ์‹คํ–‰ํ•œ ํ›„ ๊ฒฐํ•ฉ โ€” ๋‹จ๋ฝ ํ‰๊ฐ€ ๊ธˆ์ง€
  const usernameMatch = safeTimingEqual(input.username, ADMIN_USERNAME)
  const passwordMatch = safePasswordEqual(input.password)  // ํ•ญ์ƒ ์‹คํ–‰๋จ
  return usernameMatch && passwordMatch
}

3-2. safeTimingEqual โ€” ๊ธธ์ด ๋ˆ„์ถœ

function safeTimingEqual(a: string, b: string): boolean {
  // ...
  const contentEqual = timingSafeEqual(aPadded, bPadded)
  return contentEqual && aBuf.length === bBuf.length  // โ† ๋‹จ๋ฝ ํ‰๊ฐ€
}

contentEqual์ด false์ด๋ฉด aBuf.length === bBuf.length๊ฐ€ ํ‰๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ธธ์ด ๋น„๊ต๋Š” O(1)์ด๋ฏ€๋กœ ์‹ค์งˆ์  ํƒ€์ด๋ฐ ์œ„ํ˜‘์€ ๋‚ฎ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ์™„์ „ํ•œ timing-safe๋ฅผ ์œ„ํ•ด:

function safeTimingEqual(a: string, b: string): boolean {
  const aBuf = Buffer.from(a, 'utf8')
  const bBuf = Buffer.from(b, 'utf8')
  const maxLen = Math.max(aBuf.length, bBuf.length)
  const aPadded = Buffer.alloc(maxLen)
  const bPadded = Buffer.alloc(maxLen)
  aBuf.copy(aPadded)
  bBuf.copy(bPadded)
  const contentEqual = timingSafeEqual(aPadded, bPadded)
  const lengthEqual = aBuf.length === bBuf.length ? 1 : 0  // ์ƒ์ˆ˜ ์‹œ๊ฐ„์œผ๋กœ ํ‰๊ฐ€
  return (contentEqual ? 1 : 0) & lengthEqual ? true : false
}

3-3. safePasswordEqual โ€” PBKDF2 ์„ค๊ณ„ โœ… / โš ๏ธ

PBKDF2(SHA-256, 210,000 iterations)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜:

  • JWT_SECRET์„ salt๋กœ ์‚ฌ์šฉ โ€” ๋‘ ์‹œํฌ๋ฆฟ์„ ๊ฒฐํ•ฉํ•˜๋ฏ€๋กœ JWT_SECRET์„ ๊ต์ฒดํ•˜๋ฉด admin ๋กœ๊ทธ์ธ์ด ์ž๋™์œผ๋กœ ๊นจ์ง‘๋‹ˆ๋‹ค. ์ด๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋‚˜ ๋ฌธ์„œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • pbkdf2Sync ๋ชจ๋“ˆ ๋กœ๋“œ ์‹œ ์‹คํ–‰ โ€” ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ์ˆ˜๋ฐฑ ms ๋™์•ˆ ๋ธ”๋กœํ‚นํ•ฉ๋‹ˆ๋‹ค. ๋น„๋™๊ธฐ pbkdf2๋‚˜ ๋ณ„๋„ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜ ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•˜์„ธ์š”.

4. ์ฝ”๋“œ ์ •ํ™•์„ฑ / ์ถ”๊ฐ€ ๋ฒ„๊ทธ

  • verifyAdminImpersonationToken์—์„œ prefix ๋น„๊ต ์ˆœ์„œ โ€” ํ˜„์žฌ prefix๋ฅผ ๋จผ์ € ๋น„๊ตํ•œ ํ›„ signature๋ฅผ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” signature ๊ฒ€์ฆ ์ „์— prefix ๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ์•Œ ์ˆ˜ ์žˆ๋Š” ์ •๋ณด๋ฅผ ๋ˆ„์ถœํ•ฉ๋‹ˆ๋‹ค. signature ๊ฒ€์ฆ์„ ๋จผ์ € ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๋” ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค:

    // ๊ถŒ์žฅ ์ˆœ์„œ: signature ๋จผ์ € ๊ฒ€์ฆ
    if (!safeTimingEqual(signature, sign(payload))) return null
    if (!safeTimingEqual(prefix, ADMIN_IMPERSONATION_PREFIX)) return null

    (ํ˜„์žฌ๋„ safeTimingEqual์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์‹ค์ œ ์œ„ํ—˜๋„๋Š” ๋‚ฎ์œผ๋‚˜, "fail fast on MAC" ์›์น™์— ๋งž์Šต๋‹ˆ๋‹ค.)

  • verifyAdminSessionCookie์—์„œ๋„ ๋™์ผํ•œ ์ˆœ์„œ ๋ฌธ์ œ โ€” signature ๊ฒ€์ฆ ์ „์— parts.length !== 4 ์ฒดํฌ๋Š” ๊ดœ์ฐฎ์ง€๋งŒ signature๋ฅผ username ์ด์ „์— ๊ฒ€์ฆํ•˜๊ณ  ์žˆ์–ด โœ… ์ด ๋ถ€๋ถ„์€ ์˜ฌ๋ฐ”๋ฆ…๋‹ˆ๋‹ค.


5. ์š”์•ฝ

ํ•ญ๋ชฉ ์‹ฌ๊ฐ๋„ ์ƒํƒœ
verifyAdminCredentials ๋‹จ๋ฝ ํ‰๊ฐ€ ํƒ€์ด๋ฐ ๋ˆ„์ถœ ๐Ÿ”ด High ์ˆ˜์ • ํ•„์š”
PR #3๊ณผ ๋ณ‘ํ•ฉ ์ถฉ๋Œ ์œ„ํ—˜ ๐ŸŸ  Medium PR #3 close ๊ถŒ์žฅ
ADMIN_PASSWORD ์ตœ์†Œ ๊ธธ์ด ๊ฒ€์ฆ ์•ฝํ•จ (min(1)) ๐ŸŸ  Medium ์ˆ˜์ • ํ•„์š”
JWT_SECRET ํšŒ์ „ ์‹œ admin ๋กœ๊ทธ์ธ ๋ฌต์‹œ์  ํŒŒ๊ดด ๐ŸŸ  Medium ๋ฌธ์„œํ™” ํ•„์š”
pbkdf2Sync ๋ชจ๋“ˆ ๋กœ๋“œ ์‹œ ์ด๋ฒคํŠธ ๋ฃจํ”„ ๋ธ”๋กœํ‚น ๐ŸŸก Low ๊ฐœ์„  ๊ณ ๋ ค
ADMIN_USERNAME / ADMIN_PASSWORD ๋ถˆํ•„์š”ํ•œ export ๐ŸŸก Low ๋ฆฌํŒฉํ† ๋ง ๊ณ ๋ ค
.env.example ADMIN_USERNAME ๊ธฐ๋ณธ๊ฐ’ "admin" ๐ŸŸก Low ์ˆ˜์ • ๊ถŒ์žฅ
ADMIN_USERNAME, ADMIN_PASSWORD ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ด์ „ โœ… ์™„๋ฃŒ โ€”
PBKDF2 ๊ธฐ๋ฐ˜ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋น„๊ต (safePasswordEqual) โœ… ์–‘ํ˜ธ โ€”
CI ํ”Œ๋ ˆ์ด์Šคํ™€๋” ์ถ”๊ฐ€ โœ… ์™„๋ฃŒ โ€”
โœ… Actions performed

Full review triggered.

@seonghobae seonghobae changed the title ๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials ๐Ÿ›ก๏ธ [CRITICAL] ๊ด€๋ฆฌ์ž ์•„์ด๋””ยท๋น„๋ฐ€๋ฒˆํ˜ธ ํ•˜๋“œ์ฝ”๋”ฉ ์ž๊ฒฉ์ฆ๋ช… ์™„์ „ ์ œ๊ฑฐ May 30, 2026
- .jules/sentinel.md AI ์—์ด์ „ํŠธ ๋‚ด๋ถ€ ๋กœ๊ทธ ํŒŒ์ผ ์‚ญ์ œ
- getHash ํ•จ์ˆ˜์—์„œ ๋ถˆํ•„์š”ํ•œ codeql ์–ต์ œ ์ฃผ์„ ์ œ๊ฑฐ (HMAC ๋ฐฉ์‹์€ ์ ์ ˆ)
- ADMIN_PASSWORD ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ min(1)์—์„œ min(16)์œผ๋กœ ๊ฐ•ํ™”ํ•˜์—ฌ
  ์ถฉ๋ถ„ํ•œ ์—”ํŠธ๋กœํ”ผ๋ฅผ ๋ณด์žฅ
- AI ์—์ด์ „ํŠธ ์ฃผ์„(Sentinel) ์ œ๊ฑฐ

Co-Authored-By: Mastra Code (anthropic/claude-opus-4-6) <noreply@mastra.ai>
seonghobae and others added 3 commits June 1, 2026 11:33
- .jules/sentinel.md ์—์ด์ „ํŠธ ๋‚ด๋ถ€ ๋กœ๊ทธ ํŒŒ์ผ ์ œ๊ฑฐ
- .gitignore์— .jules/ ์ถ”๊ฐ€
- ADMIN_PASSWORD ์ตœ์†Œ ๊ธธ์ด๋ฅผ 16์ž๋กœ ๊ฐ•ํ™”
- Sentinel ๊ท€์† ์ฃผ์„ ๋ฐ ์ค‘๋ณต CodeQL ์–ต์ œ ์ฃผ์„ ์ œ๊ฑฐ

Co-Authored-By: Mastra Code (openai/gpt-5.5) <noreply@mastra.ai>
- ADMIN_PASSWORD๋ฅผ HMAC์œผ๋กœ ํ•ด์‹ฑํ•ด ๋น„๊ตํ•˜๋˜ safeEqual์„ ๊ณ ์ • ๊ธธ์ด ๋ฒ„ํผ timingSafeEqual ๋น„๊ต๋กœ ๋ณ€๊ฒฝ
- ์ž…๋ ฅ ๊ธธ์ด์— ์ƒํ•œ์„ ๋‘์–ด ํฐ ์ž…๋ ฅ์— ์˜ํ•œ ๋ฒ„ํผ ํ• ๋‹น DoS๋ฅผ ๋ฐฉ์ง€
- ADMIN_USERNAME์— ์ (.) ์‚ฌ์šฉ์„ ๊ธˆ์ง€ํ•ด ์„ธ์…˜/ํ† ํฐ ํŒŒ์‹ฑ ๊ณ„์•ฝ์„ ๋ณด์žฅ
- ADMIN_PASSWORD ์ตœ๋Œ€ ๊ธธ์ด๋ฅผ safeEqual ์ƒํ•œ๊ณผ ๋งž์ถค

Co-Authored-By: Mastra Code (openai/gpt-5.5) <noreply@mastra.ai>
@seonghobae

Copy link
Copy Markdown
Author

์ถ”๊ฐ€๋กœ fork PR #7์˜ CodeQL ์ฐจ๋‹จ ๋ฐ CodeRabbit ์ง€์ ๊นŒ์ง€ ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ณ€๊ฒฝ ์‚ฌํ•ญ:

  • ADMIN_PASSWORD๋ฅผ HMAC์œผ๋กœ ํ•ด์‹ฑํ•ด ๋น„๊ตํ•˜๋˜ safeEqual ๊ตฌํ˜„์„ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•ด์‹œ ์—†์ด ๊ณ ์ • ๊ธธ์ด(512 bytes) ๋ฒ„ํผ์— ๋ณต์‚ฌํ•œ ๋’ค timingSafeEqual๋กœ ๋น„๊ตํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ž…๋ ฅ์ด 512 bytes๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด ์ฆ‰์‹œ ๊ฑฐ๋ถ€ํ•˜์—ฌ ํฐ ์ž…๋ ฅ์œผ๋กœ ์ธํ•œ Buffer allocation DoS๋ฅผ ๋ฐฉ์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ADMIN_USERNAME์—๋Š” .๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋„๋ก Zod ๊ฒ€์ฆ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์„ธ์…˜/impersonation ํ† ํฐ์ด . ๊ตฌ๋ถ„์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํŒŒ์‹ฑ ๊ณ„์•ฝ์„ ๋ช…ํ™•ํžˆ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.
  • ADMIN_PASSWORD ์ตœ๋Œ€ ๊ธธ์ด๋„ safeEqual ์ƒํ•œ๊ณผ ๋งž์ถฐ max(512)๋กœ ์ œํ•œํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒ€์ฆ:

pnpm --filter @argos/shared build
AUTH_SECRET='ci-placeholder-secret-min-32-chars-here' \
JWT_SECRET='ci-placeholder-jwt-secret-min-32-chars' \
DATABASE_URL='postgresql://placeholder:placeholder@localhost:5432/placeholder' \
DIRECT_URL='postgresql://placeholder:placeholder@localhost:5432/placeholder' \
ADMIN_USERNAME='admin' \
ADMIN_PASSWORD='ci-placeholder-admin-password-min-16' \
pnpm --filter @argos/web build

๋กœ์ปฌ ๊ฒ€์ฆ์„ ํ†ต๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค. CodeQL ์žฌ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

@seonghobae

Copy link
Copy Markdown
Author

upstream PR vibemafiaclub/argos#19๊ฐ€ ์Šน์ธ ๋ฐ ๋จธ์ง€๋˜์–ด ์ด ์‚ฌ์ „ ์ž‘์—… PR์€ ๋‹ซ๊ฒ ์Šต๋‹ˆ๋‹ค. ์ถ”๊ฐ€๋กœ fork CodeQL ์‹คํŒจ๋„ ์ตœ์‹  ์ปค๋ฐ‹์—์„œ ํ•ด๊ฒฐ๋˜์–ด ๋ชจ๋“  ์ฒดํฌ๊ฐ€ ํ†ต๊ณผํ•œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@seonghobae seonghobae closed this Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants