Skip to content

hardening(security): P1 sweep — credential logging, weak hashing, timing attack, fallback identity - #389

Merged
0x5t4l1n merged 1 commit into
mainfrom
hardening/security-p1-sweep
Oct 27, 2026
Merged

0x5t4l1n merged 1 commit into
mainfrom
hardening/security-p1-sweep

Conversation

@0x5t4l1n

Copy link
Copy Markdown
Member

Summary

Post-advisory security hardening sweep. Fixes 7 P1 findings identified after the four main advisories were patched.

Changes

# File Finding Fix
1 routes/quizzes.py (×3) Body fallback identity — data.get("user_id") when JWT absent, same root cause as GHSA-p7p9 Removed fallback; identity from JWT only
2 routes/admin.py:113 print(Authorization: Bearer <ADMIN_TOKEN>) on every request Line removed
3 routes/admin.py:136 token == expected_token timing-attack-vulnerable comparison Replaced with hmac.compare_digest
4 routes/auth.py:264,386 hashlib.sha256(password) — no salt, no iterations, GPU-crackable Replaced with werkzeug.security.generate_password_hash (PBKDF2-HMAC-SHA256, salted)
5 routes/test_flow.py:12 SECRET_KEY used to decode JWT instead of JWT_SECRET_KEY — legitimate tokens always failed Fixed to use JWT_SECRET_KEY
6 routes/dashboard.py Two strings still advertised removed X-Wallet-Address header as valid auth Updated to JWT-only documentation
7 frontend/.../admin/login/page.tsx console.log('Attempting login with token:', adminToken) in browser All credential console.logs removed

⚠️ Password hash migration note

Existing users registered before this change have SHA-256 hashed passwords. check_password_hash will correctly reject them (SHA-256 hash ≠ PBKDF2 hash). Affected users will need a password reset. No data loss — old hashes remain in DB, just won't verify.

Out of scope (separate PRs)

  • Nonce replay (routes/auth.py) — requires DB schema change
  • Exam grading fallback 75 — requires compiler integration
  • Certificate blockchain mint — larger feature work

🤖 Generated with Claude Code

…en comparison, fallback identity

Fixes 7 P1 findings from post-advisory security audit:

1. routes/quizzes.py — remove body fallback identity (3 locations)
   identity.get("user_id") or data.get("user_id/wallet_address") allowed
   attacker-supplied JSON body to act as identity when JWT absent.
   Same root cause as GHSA-p7p9-jc8p-p38m. Now fails to None if no JWT.

2. routes/admin.py:113 — remove credential logging
   print(f"Admin auth check - Header: {auth_header}") logged the full
   Authorization: Bearer <ADMIN_TOKEN> value on every admin request.

3. routes/admin.py:136 — constant-time token comparison
   Replace == with hmac.compare_digest to prevent timing side-channel
   on admin token validation.

4. routes/auth.py:264,386 — replace SHA-256 no-salt with werkzeug PBKDF2
   hashlib.sha256(password.encode()).hexdigest() has no salt and no
   iterations, trivially crackable with GPU/rainbow tables.
   Replaced with werkzeug.security.generate_password_hash /
   check_password_hash (PBKDF2-HMAC-SHA256, salted, iterated).
   Note: existing SHA-256 hashes will fail check; users need password reset.

5. routes/test_flow.py:12 — fix wrong JWT decode secret
   Used SECRET_KEY (Flask session secret) instead of JWT_SECRET_KEY.
   Legitimate tokens always failed; a token signed with SECRET_KEY passed.

6. routes/dashboard.py — remove X-Wallet-Address from auth documentation
   Two strings still advertised the removed header as a supported auth
   method, misleading clients and API consumers.

7. frontend/app/admin/login/page.tsx — remove admin token console.log
   console.log('Attempting login with token:', adminToken) exposed the
   full admin token in browser DevTools on every login attempt.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@semanticdiff-com

semanticdiff-com Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  backend/routes/admin.py  45% smaller
  frontend/app/admin/login/page.tsx  43% smaller
  backend/routes/auth.py  19% smaller
  backend/routes/dashboard.py  17% smaller
  backend/routes/test_flow.py  5% smaller
  backend/routes/quizzes.py  2% smaller

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hello! Thanks for your contribution. We will review this and get back to you as soon as possible. — th30d4y

@coderabbitai

coderabbitai Bot commented Oct 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 28 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1851bf54-a2d5-4e3c-b481-09e3ef1af33a
Commits

Reviewing files that changed from the base of the PR and between 4d0efd1 and 4bd1974.

Files selected for processing: 6
  • backend/routes/admin.py
  • backend/routes/auth.py
  • backend/routes/dashboard.py
  • backend/routes/quizzes.py
  • backend/routes/test_flow.py
  • frontend/app/admin/login/page.tsx
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@0x5t4l1n
0x5t4l1n merged commit 15ceab1 into main Oct 27, 2026
10 of 16 checks passed
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