Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
31ffc60
๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials
seonghobae May 29, 2026
38d078b
๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials and CodeQL alโ€ฆ
seonghobae May 29, 2026
851618e
๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials and CodeQL alโ€ฆ
seonghobae May 29, 2026
96322ae
๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials and CodeQL alโ€ฆ
seonghobae May 29, 2026
00ed09d
๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials and CodeQL alโ€ฆ
seonghobae May 30, 2026
4aa0a93
Fix admin auth constant-time compare
Codex May 30, 2026
04215c4
๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials and CodeQL alโ€ฆ
seonghobae May 30, 2026
d75a4e8
Harden admin credential comparisons
Codex May 30, 2026
982d2de
Make admin auth KDF encoding explicit
Codex May 30, 2026
336e8d3
๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials and CodeQL alโ€ฆ
seonghobae Jun 1, 2026
2c332fc
fix: ๋ฆฌ๋ทฐ ๋ฐ˜์˜ - .jules/sentinel.md ์‚ญ์ œ, codeql ์–ต์ œ ์ฃผ์„ ์ œ๊ฑฐ, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ตœ์†Œ ๊ธธ์ด ๊ฐ•ํ™”
seonghobae Jun 1, 2026
8a95f27
๐Ÿ›ก๏ธ Sentinel: [CRITICAL] Fix hardcoded admin credentials and CodeQL alโ€ฆ
seonghobae Jun 1, 2026
e68ed59
fix: ๊ด€๋ฆฌ์ž ์ž๊ฒฉ์ฆ๋ช… ๋ฆฌ๋ทฐ ๋ฐ˜์˜
seonghobae Jun 1, 2026
bef3156
fix: CodeQL ๊ฒฝ๊ณ  ์ œ๊ฑฐ๋ฅผ ์œ„ํ•ด ๊ด€๋ฆฌ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•ด์‹œ ๋น„๊ต ์ œ๊ฑฐ
seonghobae Jun 1, 2026
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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ jobs:
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: "ci-admin"
ADMIN_PASSWORD: "ci-admin-password"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ backups/
persuasion-data/runs/
__pycache__/
*.pyc
.jules/
2 changes: 2 additions & 0 deletions packages/web/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ AUTH_SECRET=replace-with-min-32-char-random-string
DATABASE_URL="postgresql://postgres.[project]:[password]@aws-0-ap-northeast-1.pooler.supabase.com:6543/postgres?pgbouncer=true"
DIRECT_URL="postgresql://postgres.[project]:[password]@db.uwxfseowdzuuepeeudrx.supabase.co:5432/postgres"
JWT_SECRET="replace-with-32-char-minimum-random-string"
ADMIN_USERNAME="admin"
ADMIN_PASSWORD="replace-with-secure-admin-password"
21 changes: 16 additions & 5 deletions packages/web/src/lib/server/admin-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@ import { NextRequest, NextResponse } from 'next/server'

import { env } from './env'

export const ADMIN_USERNAME = 'admin'
export const ADMIN_PASSWORD = 'og9oRajx7h88v1RIj3eDgdrh9jgLYVV3'
export const ADMIN_USERNAME = env.ADMIN_USERNAME
export const ADMIN_PASSWORD = env.ADMIN_PASSWORD

const ADMIN_SESSION_COOKIE = 'argos_admin_session'
const ADMIN_SESSION_TTL_MS = 12 * 60 * 60 * 1000
const ADMIN_IMPERSONATION_TTL_MS = 60 * 1000
const ADMIN_IMPERSONATION_PREFIX = 'argos_imp'
const MAX_SAFE_EQUAL_BYTES = 512

function safeEqual(a: string, b: string): boolean {
const aHash = createHmac('sha256', env.JWT_SECRET).update(a).digest()
const bHash = createHmac('sha256', env.JWT_SECRET).update(b).digest()
return timingSafeEqual(aHash, bHash)
const aBytes = Buffer.from(a)
const bBytes = Buffer.from(b)

if (aBytes.length > MAX_SAFE_EQUAL_BYTES || bBytes.length > MAX_SAFE_EQUAL_BYTES) {
return false
}

const aPadded = Buffer.alloc(MAX_SAFE_EQUAL_BYTES)
const bPadded = Buffer.alloc(MAX_SAFE_EQUAL_BYTES)
aBytes.copy(aPadded)
bBytes.copy(bPadded)

return timingSafeEqual(aPadded, bPadded) && aBytes.length === bBytes.length
}

function sign(payload: string): string {
Expand Down
4 changes: 4 additions & 0 deletions packages/web/src/lib/server/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ 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).max(128).refine((value) => !value.includes('.'), {
message: 'ADMIN_USERNAME must not contain "."',
}),
ADMIN_PASSWORD: z.string().min(16).max(512),
})

export const env = EnvSchema.parse(process.env)
Loading