Skip to content

๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials#35

Closed
seonghobae wants to merge 2 commits into
mainfrom
sentinel-fix-hardcoded-admin-credentials-2027270219903167306
Closed

๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials#35
seonghobae wants to merge 2 commits into
mainfrom
sentinel-fix-hardcoded-admin-credentials-2027270219903167306

Conversation

@seonghobae

Copy link
Copy Markdown

๐Ÿšจ Severity: CRITICAL
๐Ÿ’ก Vulnerability: Hardcoded ADMIN_USERNAME and ADMIN_PASSWORD were discovered in packages/web/src/lib/server/admin-auth.ts.
๐ŸŽฏ Impact: Anyone with read access to the repository could discover the administrator credentials, leading to a full authentication bypass and unauthorized administrative access. Furthermore, hardcoded credentials cannot be easily rotated or managed per-environment.
๐Ÿ”ง Fix:

  • Added ADMIN_USERNAME and ADMIN_PASSWORD to the Zod environment schema in packages/web/src/lib/server/env.ts to ensure they are required at runtime.
  • Replaced the hardcoded strings in admin-auth.ts with references to env.ADMIN_USERNAME and env.ADMIN_PASSWORD, preserving the existing export const API contract.
  • Updated packages/web/.env.example and .github/workflows/ci.yml to include the new required environment variables to prevent CI/CD regressions.
  • Logged the security learning in .jules/sentinel.md.
    โœ… Verification:
  • Run pnpm run build and pnpm lint.
  • Verify the CI pipeline passes.
  • Try to start the server without setting ADMIN_USERNAME and ADMIN_PASSWORDโ€”it should fail to start.

PR created automatically by Jules for task 2027270219903167306 started by @seonghobae

@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 Jun 7, 2026

Copy link
Copy Markdown

Review Change Stack

๐Ÿ“ Walkthrough

Summary by CodeRabbit

  • ๋ณด์•ˆ ๊ฐœ์„ 

    • ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช…์ด ๋” ์ด์ƒ ํ•˜๋“œ์ฝ”๋”ฉ๋˜์ง€ ์•Š๊ณ  ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.
    • ๊ด€๋ฆฌ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์ตœ์†Œ 8์ž ์ด์ƒ์ด์–ด์•ผ ํ•˜๋ฉฐ ๋Ÿฐํƒ€์ž„์—์„œ ๊ฒ€์ฆ๋ฉ๋‹ˆ๋‹ค.
    • ํ™˜๊ฒฝ ์„ค์ • ์˜ˆ์ œ์— ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช… ํ…œํ”Œ๋ฆฟ์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์‹ ๋ขฐ์„ฑ ๊ฐœ์„ 

    • ๊ด€๋ฆฌ์ž ๋กœ๊ทธ์ธ ๊ฒ€์ฆ ํ๋ฆ„์ด ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋กœ ๋ณ€๊ฒฝ๋˜์–ด ์ธ์ฆ ์ฒ˜๋ฆฌ์˜ ์•ˆ์ „์„ฑ๊ณผ ์ผ๊ด€์„ฑ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค.
  • CI

    • ๋นŒ๋“œ ์›Œํฌํ”Œ๋กœ์šฐ์— ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช… ํ”Œ๋ ˆ์ด์Šคํ™€๋”๊ฐ€ ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Walkthrough

๊ด€๋ฆฌ์ž ๊ณ„์ • ์ •๋ณด๋ฅผ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์ด๋™ํ•˜๊ณ  Zod ๊ฒ€์ฆ์„ ์ถ”๊ฐ€ํ–ˆ์œผ๋ฉฐ, PBKDF2 ๊ธฐ๋ฐ˜ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ์œผ๋กœ ๋กœ๊ทธ์ธ ํ๋ฆ„์„ ๋น„๋™๊ธฐํ™”ํ•˜๊ณ  .env.example ๋ฐ CI์— ํ”Œ๋ ˆ์ด์Šคํ™€๋”๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

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

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

Layer / File(s) Summary
ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ฒ€์ฆ ์Šคํ‚ค๋งˆ
packages/web/src/lib/server/env.ts
์„œ๋ฒ„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์Šคํ‚ค๋งˆ์— ADMIN_USERNAME (trim ํ›„ ์ตœ์†Œ 1์ž) ๋ฐ ADMIN_PASSWORD (trim ํ›„ ์ตœ์†Œ 8์ž)๋ฅผ ํ•„์ˆ˜๋กœ ์ถ”๊ฐ€ํ•˜์—ฌ ๋Ÿฐํƒ€์ž„์—์„œ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
๊ด€๋ฆฌ์ž ์ธ์ฆ ๊ตฌํ˜„ ์—…๋ฐ์ดํŠธ ๋ฐ ํ•ด์‹œ ๊ฒ€์ฆ
packages/web/src/lib/server/admin-auth.ts
๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช…์„ env์—์„œ ์ฝ๋„๋ก ๋ณ€๊ฒฝํ•˜๊ณ  PBKDF2 ํ•ด์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๋ชจ๋“ˆ ์ดˆ๊ธฐ์˜ TARGET_PASSWORD_HASH๋ฅผ ๋„์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค. verifyAdminCredentials๋Š” ์ž…๋ ฅ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋น„๋™๊ธฐ pbkdf2๋กœ ํ•ด์‹œํ•œ ๋’ค timingSafeEqual๋กœ ๋น„๊ตํ•˜๋„๋ก ๋™์ž‘๊ณผ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
๋กœ๊ทธ์ธ ๋ผ์šฐํŠธ ํ†ตํ•ฉ
packages/web/src/app/api/admin/login/route.ts
๊ด€๋ฆฌ์ž ๋กœ๊ทธ์ธ POST ํ•ธ๋“ค๋Ÿฌ์—์„œ verifyAdminCredentials ํ˜ธ์ถœ์„ await ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•ด ๋น„๋™๊ธฐ ๊ฒ€์ฆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
ํ™˜๊ฒฝ ์„ค์ • ๋ฐ CI ์›Œํฌํ”Œ๋กœ์šฐ
packages/web/.env.example, .github/workflows/ci.yml
.env.example์— ADMIN_USERNAME/ADMIN_PASSWORD ํ…œํ”Œ๋ฆฟ์„ ์ถ”๊ฐ€ํ–ˆ๊ณ , CI์˜ argos/web build ๋‹จ๊ณ„ env์— ํ”Œ๋ ˆ์ด์Šคํ™€๋”๋ฅผ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
๋ณด์•ˆ ๊ฐœ์„  ๋ฌธ์„œํ™”
.jules/sentinel.md
ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช… ์ทจ์•ฝ์ ๊ณผ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ „ํ™˜ ๋ฐ ๊ฒ€์ฆ ์ ์šฉ์„ ๊ธฐ๋กํ•œ ์„ผํ‹ฐ๋„ฌ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

Sequence Diagram(s):

sequenceDiagram
  participant Client as ํด๋ผ์ด์–ธํŠธ
  participant API as POST /api/admin/login
  participant Auth as admin-auth (verifyAdminCredentials)
  Client->>API: ๋กœ๊ทธ์ธ ์š”์ฒญ (username, password)
  API->>Auth: await verifyAdminCredentials({username, password})
  Auth->>Auth: pbkdf2Async(input password) -> ํ•ด์‹œ ๋น„๊ต(timingSafeEqual) against TARGET_PASSWORD_HASH
  Auth-->>API: ๊ฒ€์ฆ ๊ฒฐ๊ณผ (true/false)
  API-->>Client: 200 + ์„ธ์…˜ ์ฟ ํ‚ค ๋˜๋Š” 401
Loading

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

๐ŸŽฏ 3 (Moderate) | โฑ๏ธ ~20 minutes

์‹œ

๐Ÿฐ ํ™˜๊ฒฝ๋ณ€์ˆ˜์— ์ˆจ๊ธด ๋‹น๊ทผ ํ•œ ์Œˆ,
PBKDF2๋กœ ๋น„๋ฐ€๋ฒˆํ˜ธ๋„ ๊ฐ์‹ธ๋„ค,
Zod๊ฐ€ ์ง€ํ‚ค๋‹ˆ ๋Ÿฐํƒ€์ž„๋„ ๋“ ๋“ ,
CI์™€ ์˜ˆ์ œ์—” ํ”Œ๋ ˆ์ด์Šคํ™€๋” ์ฒ™์ฒ™,
ํ† ๋ผ๊ฐ€ ์ถ•ํ•˜ํ•˜๋…ธ๋ผ, ํŠผํŠผํ•œ ๋ณด์•ˆ!


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
Title check โœ… Passed ์ œ๋ชฉ์€ PR์˜ ์ฃผ์š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์ธ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช… ์ œ๊ฑฐ๋ผ๋Š” ํ•ต์‹ฌ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์š”์•ฝํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
Description check โœ… Passed ์„ค๋ช…์€ ํ•˜๋“œ์ฝ”๋”ฉ๋œ ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช… ๋ฌธ์ œ, ์˜ํ–ฅ๋„, ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•, ๊ฒ€์ฆ ๋ฐฉ๋ฒ•์„ ํฌํ•จํ•˜์—ฌ ๋ณ€๊ฒฝ์‚ฌํ•ญ๊ณผ ์ถฉ๋ถ„ํžˆ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
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.
โœจ Finishing Touches
๐Ÿ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
๐Ÿงช Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sentinel-fix-hardcoded-admin-credentials-2027270219903167306
โœจ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch sentinel-fix-hardcoded-admin-credentials-2027270219903167306

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.

@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: 1

๐Ÿค– 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 2: Update the sentinel entry heading that currently reads "## 2024-05-24
- [CRITICAL] Fix Hardcoded Admin Credentials in Authentication Logic" so the
date reflects the actual PR creation/fix date (change 2024-05-24 to 2026-06-07);
locate and edit the header line in .jules/sentinel.md (the "## ... - [CRITICAL]
Fix Hardcoded Admin Credentials in Authentication Logic" line) to use the
corrected date.
๐Ÿช„ 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: f5d1fddb-993c-456b-a712-dfd0d04a92ea

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between cdf4ce8 and 35e4a20.

๐Ÿ“’ 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
@@ -0,0 +1,5 @@

## 2024-05-24 - [CRITICAL] Fix Hardcoded Admin Credentials in Authentication Logic

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

์„ผํ‹ฐ๋„ฌ ๊ธฐ๋ก์˜ ๋‚ ์งœ๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”.

๋ฌธ์„œ์— ๊ธฐ๋ก๋œ ๋‚ ์งœ๊ฐ€ 2024-05-24์ด์ง€๋งŒ ์ด PR์€ 2026-06-07์— ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์„ผํ‹ฐ๋„ฌ ๊ธฐ๋ก์˜ ๋‚ ์งœ๋Š” ์‹ค์ œ ์ˆ˜์ •์ด ์ด๋ฃจ์–ด์ง„ ๋‚ ์งœ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ๋ฐ˜์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ ๋‚ ์งœ ์ˆ˜์ • ์ œ์•ˆ
-## 2024-05-24 - [CRITICAL] Fix Hardcoded Admin Credentials in Authentication Logic
+## 2026-06-07 - [CRITICAL] Fix Hardcoded Admin Credentials in Authentication Logic
๐Ÿ“ 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-24 - [CRITICAL] Fix Hardcoded Admin Credentials in Authentication Logic
## 2026-06-07 - [CRITICAL] Fix Hardcoded Admin Credentials in Authentication Logic
๐Ÿค– 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 2, Update the sentinel entry heading that
currently reads "## 2024-05-24 - [CRITICAL] Fix Hardcoded Admin Credentials in
Authentication Logic" so the date reflects the actual PR creation/fix date
(change 2024-05-24 to 2026-06-07); locate and edit the header line in
.jules/sentinel.md (the "## ... - [CRITICAL] Fix Hardcoded Admin Credentials in
Authentication Logic" line) to use the corrected date.

@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 | ๐ŸŸก Minor

ADMIN_PASSWORD ์™ธ๋ถ€ ๋‚ด๋ณด๋‚ด๊ธฐ(export) ์ œ๊ฑฐ ์š”์ฒญ (admin-auth.ts 10-11)

ADMIN_PASSWORD๋Š” TARGET_PASSWORD_HASH๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐ๋งŒ ํ•„์š”ํ•˜๋ฉฐ, ํ˜„์žฌ export const ADMIN_PASSWORD๋กœ ํ‰๋ฌธ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ชจ๋“ˆ ์ธํ„ฐํŽ˜์ด์Šค์— ๋…ธ์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ADMIN_PASSWORD๋ฅผ ๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ named import๋กœ ์‚ฌ์šฉํ•˜๋Š” ํ”์ ๋„ ์—†์–ด const๋กœ ๋น„๋‚ด๋ณด๋‚ด๋Š” ๊ฒŒ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”’ ํ‰๋ฌธ ๋น„๋ฐ€๋ฒˆํ˜ธ ๋…ธ์ถœ ์ œ๊ฑฐ
-export const ADMIN_USERNAME = env.ADMIN_USERNAME
-export const ADMIN_PASSWORD = env.ADMIN_PASSWORD
+export const ADMIN_USERNAME = env.ADMIN_USERNAME
+const ADMIN_PASSWORD = env.ADMIN_PASSWORD
๐Ÿค– 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,
ADMIN_PASSWORD is currently exported but only needed internally to compute
TARGET_PASSWORD_HASH; change export const ADMIN_PASSWORD to a non-exported const
(remove export) and keep export for ADMIN_USERNAME only; update any internal
uses in this module to reference the new local const and ensure no other modules
import ADMIN_PASSWORD (remove or refactor those imports if present) so the
plaintext password is not exposed from admin-auth.ts.
๐Ÿค– 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 49-62: Always run the PBKDF2 hashing regardless of the username
match to avoid timing leakage: call pbkdf2Async(...) unconditionally, compute
passwordMatch = timingSafeEqual(inputPasswordHash, TARGET_PASSWORD_HASH),
compute usernameMatch = safeEqual(input.username, ADMIN_USERNAME), then return
usernameMatch && passwordMatch (ensure inputPasswordHash is computed before
those comparisons). Reference pbkdf2Async, timingSafeEqual, safeEqual,
ADMIN_USERNAME, TARGET_PASSWORD_HASH, and the HASH_* constants when making the
change.
- Around line 20-24: Replace the hardcoded HASH_SALT in admin-auth.ts with an
environment-driven salt: add an ADMIN_PASSWORD_SALT (or
ADMIN_PASSWORD_HASH+ADMIN_PASSWORD_SALT) to the app env module (e.g., export it
from packages/web/src/lib/server/env.ts) and update the code paths that
reference HASH_SALT to read the salt from that env variable; if you choose to
store ADMIN_PASSWORD_HASH instead of plain ADMIN_PASSWORD, adapt the
authentication routines (the PBKDF2/verify logic in admin-auth.ts that uses
HASH_ITERATIONS, HASH_KEYLEN, HASH_DIGEST) to compare against the provided hash
and use the env salt, and ensure a clear runtime error is thrown when the
required env variables are missing.

---

Outside diff comments:
In `@packages/web/src/lib/server/admin-auth.ts`:
- Around line 10-11: ADMIN_PASSWORD is currently exported but only needed
internally to compute TARGET_PASSWORD_HASH; change export const ADMIN_PASSWORD
to a non-exported const (remove export) and keep export for ADMIN_USERNAME only;
update any internal uses in this module to reference the new local const and
ensure no other modules import ADMIN_PASSWORD (remove or refactor those imports
if present) so the plaintext password is not exposed from admin-auth.ts.
๐Ÿช„ 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: 357ab05c-bbf0-4bfd-b40f-d192c154695f

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 35e4a20 and 35294a4.

๐Ÿ“’ Files selected for processing (2)
  • packages/web/src/app/api/admin/login/route.ts
  • packages/web/src/lib/server/admin-auth.ts

Comment on lines +20 to +24
// PBKDF2 parameters for secure password hashing
const HASH_SALT = 'argos_admin_salt'
const HASH_ITERATIONS = 100000
const HASH_KEYLEN = 64
const HASH_DIGEST = 'sha512'

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 | ๐Ÿ—๏ธ Heavy lift

์ •์  ์†”ํŠธ ์‚ฌ์šฉ์€ ๋ณด์•ˆ ๋ชจ๋ฒ” ์‚ฌ๋ก€ ์œ„๋ฐ˜

HASH_SALT๊ฐ€ ์†Œ์Šค ์ฝ”๋“œ์— ํ•˜๋“œ์ฝ”๋”ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณต๊ฒฉ์ž๊ฐ€ ์†Œ์Šค ์ฝ”๋“œ์— ์ ‘๊ทผํ•˜๋ฉด ์ด ์†”ํŠธ๋กœ ๋ ˆ์ธ๋ณด์šฐ ํ…Œ์ด๋ธ”์„ ์‚ฌ์ „ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ถŒ์žฅ ํ•ด๊ฒฐ์ฑ…:

  • ADMIN_PASSWORD_SALT ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ๋ฐฐํฌ ์‹œ ๋žœ๋ค ์ƒ์„ฑ๋œ ๊ฐ’ ์‚ฌ์šฉ
  • ๋˜๋Š” ADMIN_PASSWORD ๋Œ€์‹  ์ด๋ฏธ ํ•ด์‹œ๋œ ADMIN_PASSWORD_HASH์™€ ์†”ํŠธ๋ฅผ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์ €์žฅ

๋‹จ์ผ ๊ด€๋ฆฌ์ž ๊ณ„์ •์— 100k iterations๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ฆ‰๊ฐ์ ์ธ ์œ„ํ˜‘์€ ์•„๋‹ˆ์ง€๋งŒ, ๋ณด์•ˆ ์‹ฌ์ธต ๋ฐฉ์–ด ์ธก๋ฉด์—์„œ ๊ฐœ์„ ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ›ก๏ธ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๊ธฐ๋ฐ˜ ์†”ํŠธ ์‚ฌ์šฉ ์ œ์•ˆ

packages/web/src/lib/server/env.ts์— ์ถ”๊ฐ€:

 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().trim().min(1),
   ADMIN_PASSWORD: z.string().trim().min(8),
+  ADMIN_PASSWORD_SALT: z.string().min(16),
 })

admin-auth.ts ์ˆ˜์ •:

-const HASH_SALT = 'argos_admin_salt'
+const HASH_SALT = env.ADMIN_PASSWORD_SALT
๐Ÿค– 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 20 - 24, Replace the
hardcoded HASH_SALT in admin-auth.ts with an environment-driven salt: add an
ADMIN_PASSWORD_SALT (or ADMIN_PASSWORD_HASH+ADMIN_PASSWORD_SALT) to the app env
module (e.g., export it from packages/web/src/lib/server/env.ts) and update the
code paths that reference HASH_SALT to read the salt from that env variable; if
you choose to store ADMIN_PASSWORD_HASH instead of plain ADMIN_PASSWORD, adapt
the authentication routines (the PBKDF2/verify logic in admin-auth.ts that uses
HASH_ITERATIONS, HASH_KEYLEN, HASH_DIGEST) to compare against the provided hash
and use the env salt, and ensure a clear runtime error is thrown when the
required env variables are missing.

Comment on lines +49 to +62
if (!safeEqual(input.username, ADMIN_USERNAME)) {
return false
}

// Hash the incoming password asynchronously to avoid blocking the event loop
const inputPasswordHash = await pbkdf2Async(
input.password,
HASH_SALT,
HASH_ITERATIONS,
HASH_KEYLEN,
HASH_DIGEST
)

return timingSafeEqual(inputPasswordHash, TARGET_PASSWORD_HASH)

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 49-51), ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ์€ PBKDF2 ํ•ด์‹œ ๊ณ„์‚ฐ ํ›„ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„ ์ฐจ์ด(~์ˆ˜๋ฐฑms)๋กœ ๊ณต๊ฒฉ์ž๊ฐ€ ์œ ํšจํ•œ ์‚ฌ์šฉ์ž๋ช…์„ ์—ด๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ์ผ ๊ด€๋ฆฌ์ž ๊ณ„์ • ์‹œ์Šคํ…œ์—์„œ๋Š” ์œ„ํ—˜๋„๊ฐ€ ๋‚ฎ์ง€๋งŒ, ์™„์ „ํ•œ ์ƒ์ˆ˜ ์‹œ๊ฐ„ ๊ฒ€์ฆ์„ ์œ„ํ•ด ์‚ฌ์šฉ์ž๋ช…๊ณผ ๊ด€๊ณ„์—†์ด ํ•ญ์ƒ PBKDF2๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

โฑ๏ธ ์ƒ์ˆ˜ ์‹œ๊ฐ„ ๊ฒ€์ฆ ์ œ์•ˆ
 export async function verifyAdminCredentials(input: {
   username: string
   password: string
 }): Promise<boolean> {
-  if (!safeEqual(input.username, ADMIN_USERNAME)) {
-    return false
-  }
-
   // Hash the incoming password asynchronously to avoid blocking the event loop
   const inputPasswordHash = await pbkdf2Async(
     input.password,
     HASH_SALT,
     HASH_ITERATIONS,
     HASH_KEYLEN,
     HASH_DIGEST
   )
 
-  return timingSafeEqual(inputPasswordHash, TARGET_PASSWORD_HASH)
+  const usernameMatch = safeEqual(input.username, ADMIN_USERNAME)
+  const passwordMatch = timingSafeEqual(inputPasswordHash, TARGET_PASSWORD_HASH)
+  return usernameMatch && passwordMatch
 }
๐Ÿ“ 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
if (!safeEqual(input.username, ADMIN_USERNAME)) {
return false
}
// Hash the incoming password asynchronously to avoid blocking the event loop
const inputPasswordHash = await pbkdf2Async(
input.password,
HASH_SALT,
HASH_ITERATIONS,
HASH_KEYLEN,
HASH_DIGEST
)
return timingSafeEqual(inputPasswordHash, TARGET_PASSWORD_HASH)
// Hash the incoming password asynchronously to avoid blocking the event loop
const inputPasswordHash = await pbkdf2Async(
input.password,
HASH_SALT,
HASH_ITERATIONS,
HASH_KEYLEN,
HASH_DIGEST
)
const usernameMatch = safeEqual(input.username, ADMIN_USERNAME)
const passwordMatch = timingSafeEqual(inputPasswordHash, TARGET_PASSWORD_HASH)
return usernameMatch && passwordMatch
๐Ÿค– 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 49 - 62, Always run
the PBKDF2 hashing regardless of the username match to avoid timing leakage:
call pbkdf2Async(...) unconditionally, compute passwordMatch =
timingSafeEqual(inputPasswordHash, TARGET_PASSWORD_HASH), compute usernameMatch
= safeEqual(input.username, ADMIN_USERNAME), then return usernameMatch &&
passwordMatch (ensure inputPasswordHash is computed before those comparisons).
Reference pbkdf2Async, timingSafeEqual, safeEqual, ADMIN_USERNAME,
TARGET_PASSWORD_HASH, and the HASH_* constants when making the change.

@seonghobae

Copy link
Copy Markdown
Author

์ตœ์‹  upstream/main ๊ธฐ์ค€์œผ๋กœ ์ด PR์€ 82๊ฐœ ํŒŒ์ผ์˜ stale diff๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ .claude agent/skill ํŒŒ์ผ ์‚ญ์ œ์™€ ์˜ค๋ž˜๋œ ์›Œํฌํ”Œ๋กœ์šฐ/lockfile/env ๋ณ€๊ฒฝ์ด ์„ž์—ฌ ์žˆ์–ด ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜ upstream์— ์˜ฌ๋ฆฌ๋ฉด ์ด๋ฏธ ๋ฐ˜์˜๋œ ๋ณ€๊ฒฝ์„ ๋˜๋Œ๋ฆด ์œ„ํ—˜์ด ํฝ๋‹ˆ๋‹ค.

ํ˜„์žฌ ํ๋Š” upstream #30 โ†’ upstream #21 ์ˆœ์„œ๋กœ ์ •๋ฆฌ ์ค‘์ž…๋‹ˆ๋‹ค. ์ด PR์˜ ์•„์ด๋””์–ด๊ฐ€ ์—ฌ์ „ํžˆ ํ•„์š”ํ•˜๋ฉด ์ตœ์‹  upstream/main์—์„œ ๋‹จ์ผ ๋ชฉ์  ๋ธŒ๋žœ์น˜๋กœ ๊นจ๋—ํ•˜๊ฒŒ ๋‹ค์‹œ ์ถ”์ถœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. stale PR๋กœ ๋‹ซ์Šต๋‹ˆ๋‹ค.

@seonghobae seonghobae closed this Jun 10, 2026
@google-labs-jules

Copy link
Copy Markdown

์ตœ์‹  upstream/main ๊ธฐ์ค€์œผ๋กœ ์ด PR์€ 82๊ฐœ ํŒŒ์ผ์˜ stale diff๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ .claude agent/skill ํŒŒ์ผ ์‚ญ์ œ์™€ ์˜ค๋ž˜๋œ ์›Œํฌํ”Œ๋กœ์šฐ/lockfile/env ๋ณ€๊ฒฝ์ด ์„ž์—ฌ ์žˆ์–ด ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๊ฑฐ๋‚˜ upstream์— ์˜ฌ๋ฆฌ๋ฉด ์ด๋ฏธ ๋ฐ˜์˜๋œ ๋ณ€๊ฒฝ์„ ๋˜๋Œ๋ฆด ์œ„ํ—˜์ด ํฝ๋‹ˆ๋‹ค.

ํ˜„์žฌ ํ๋Š” upstream #30 โ†’ upstream #21 ์ˆœ์„œ๋กœ ์ •๋ฆฌ ์ค‘์ž…๋‹ˆ๋‹ค. ์ด PR์˜ ์•„์ด๋””์–ด๊ฐ€ ์—ฌ์ „ํžˆ ํ•„์š”ํ•˜๋ฉด ์ตœ์‹  upstream/main์—์„œ ๋‹จ์ผ ๋ชฉ์  ๋ธŒ๋žœ์น˜๋กœ ๊นจ๋—ํ•˜๊ฒŒ ๋‹ค์‹œ ์ถ”์ถœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. stale PR๋กœ ๋‹ซ์Šต๋‹ˆ๋‹ค.

Understood. Acknowledging that this work is now obsolete and stopping work on this task.

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.

1 participant