Add PEPPER to password handling for improved security#81
Add PEPPER to password handling for improved security#81JonanOribe wants to merge 10 commits intosmittix:mainfrom
Conversation
Introduces a PEPPER value from config and appends it to passwords during both admin user creation and login authentication. This enhances password security by making hashes more resilient to attacks.
smittix
left a comment
There was a problem hiding this comment.
Thanks for the contribution! The pepper concept is good for defense-in-depth, but there are two issues that need to be addressed before merging:
1. Hardcoded Default Pepper
PEPPER = _get_env('PEPPER', '7aJBLRSimPO0l6Wkfic8YhO3PPqwPwD7oikTfK4TYjzIFxS4Tk')A pepper's security comes from being secret and not in the source code. With a hardcoded default, anyone with access to the repo has the pepper, defeating its purpose.
Suggested fix: Either:
- Require explicit configuration (no default) and fail startup if not set
- Generate a random pepper on first run and store it in the database or a local file outside the repo
- Document that users must set a custom
PEPPERenv var in production
2. Breaking Change for Existing Accounts
After this change, existing admin accounts will fail to authenticate because:
- Existing password hash =
hash(password) - New login check =
hash(password + pepper)
These won't match.
Suggested fix: Add a migration path:
- Option A: On first run after upgrade, detect missing pepper and rehash existing passwords
- Option B: Add a one-time migration command/script
- Option C: At minimum, document that users need to reset their admin password after upgrading
Once these are addressed, happy to merge!
|
Thank you for the detailed feedback. These are excellent points regarding security and the upgrade path. I will be implementing the following changes to address them:
I will remove the hardcoded default pepper to ensure the secret is never part of the source code. I will adopt the following approach:
To handle the transition without locking out current users, I will implement a "Lazy Rehash" strategy:
To be honest, I left the PEPPER hardcoded, much like the default database username and password, assuming that the first thing any user would do after cloning the repo for deployment is customize these values. However, I agree that your approach is much cleaner and more secure. I will push these updates as soon as they are ready. |
Introduces secure PEPPER-based password hashing for user authentication. Updates documentation and setup to require a unique INTERCEPT_PEPPER environment variable, modifies login logic to use the new verification method, and adds automatic migration for legacy password hashes. Updates dependencies and Docker configuration to support these changes.
|
I've implemented the requested changes. This includes both the UV requirements and functionality, as well as Docker and setup.sh. I've tested it, but please review it carefully in case you find anything missing, as there are many possible combinations and I don't want to have overlooked anything. I've also added the missing dependencies to the .toml file after the latest updates. |
smittix
left a comment
There was a problem hiding this comment.
Thanks for the contribution! The pepper implementation and lazy migration approach are solid concepts. However, there are a few issues that need to be addressed before this can be merged:
Critical: PEPPER can be None - No fail-fast validation
The author mentioned implementing "fail-fast initialization" in the comments, but it wasn't actually implemented:
# config.py:150
PEPPER = os.environ.get('INTERCEPT_PEPPER') # Returns None if not setWhen INTERCEPT_PEPPER is not set:
f"{password}{PEPPER}"becomes"adminNone"instead of failing- Admin user gets created with hash of
"adminNone" - If PEPPER is later set, all existing users get locked out
Suggested fix: Add startup validation in app.py (in main()) or config.py:
if PEPPER is None:
raise RuntimeError("INTERCEPT_PEPPER environment variable must be set. See README for setup instructions.")Debug print() statements left in production code
# utils/database.py:36, 52, 57
print(f"Verifying user: {username} at {datetime.now()}")
print(f"User '{username}' new verified at {datetime.now()}")
print(f"User '{username}' legacy verified at {datetime.now()}")These should be logger.debug() calls or removed entirely.
Duplicate import
# utils/database.py:15
from werkzeug.security import generate_password_hash, check_password_hash
# utils/database.py:27
from werkzeug.security import check_password_hash, generate_password_hashThe second import on line 27 is redundant and should be removed.
Missing test coverage
The new verify_user() function has no test coverage. Consider adding tests for:
- Successful login with peppered hash
- Legacy hash detection and migration
- Failed login attempts
- Behavior when PEPPER is properly set
Once these are addressed, this will be good to merge!
Require the INTERCEPT_PEPPER environment variable at startup and raise an error if unset. Add comprehensive tests for user verification, including legacy password hash migration to peppered hashes, successful and failed logins, and user-not-found scenarios. Also, remove unused PEPPER import from app.py.
Deleting prints
smittix
left a comment
There was a problem hiding this comment.
Thanks for adding PEPPER support - this is a solid security enhancement! The migration logic for legacy passwords is well thought out.
However, there are some issues that should be addressed before merging:
1. Hard crash on missing PEPPER is too aggressive
PEPPER = os.environ.get('INTERCEPT_PEPPER')
if PEPPER is None:
raise RuntimeError("INTERCEPT_PEPPER environment variable must be set...")This will immediately break all existing installations on upgrade. Consider:
- Log a warning but allow the app to start in "legacy mode" for a grace period
- Or generate a random PEPPER on first run and save it to a file/DB
- At minimum, make this a loud warning rather than a hard crash
2. Docker placeholder is dangerous
- INTERCEPT_PEPPER=your_generated_secret_hereIf users don't change this, all Docker installs share the same PEPPER, defeating the security benefit entirely. Instead:
- Remove from docker-compose.yml
- Add to
.env.examplewith clear instructions - Document that users MUST set this before first run
3. Unused import left in app.py
The refactor moves password checking to verify_user(), but check_password_hash import from werkzeug will be left unused in app.py. Please remove it.
4. Unrelated dependency additions
These in pyproject.toml don't seem related to PEPPER:
'psycopg2-binary>=2.9.9',
'numpy>=1.24.0',
'scipy>=1.10.0'
Please remove or split into a separate PR.
5. Whitespace noise in config.py
The diff shows trailing whitespace changes throughout config.py that obscure the actual changes. Please revert the whitespace-only changes.
The core security feature is good - just needs these cleanup items addressed. Let me know if you have questions!

Introduces a PEPPER value from config and appends it to passwords during both admin user creation and login authentication. This enhances password security by making hashes more resilient to attacks.