Conversation
Security: - Admin API endpoints called check_admin_priv() but discarded the result, leaving all 7 /api/admin and /api/db routes unauthenticated; new fail-closed require_admin decorator returns 403, and db_dump no longer returns password hashes or raw token values - SECRET_KEY moved to MICHMONEY_SECRET_KEY env var (dev-only fallback with rotation warning); real user rows and admin tokens in sql/data.sql replaced with fake dev seeds. The old key, three admin tokens, and real user credentials remain in git history and must be rotated - CSRF tokens on all form POSTs; logout/delete POST-only; delete requires login; session.pop fixes anonymous 500s - Non-ASCII Authorization header and CSRF token now rejected cleanly (403/400) instead of raising TypeError -> 500 in hmac.compare_digest - Restored MAX_CONTENT_LENGTH request-body cap - bin/run prod runs gunicorn on 127.0.0.1 instead of sudo flask --debug Correctness: - add_admin/remove_admin 500'd on every request (phantom params) - Hardcoded UTC-5 replaced with DST-correct zoneinfo America/Detroit - Atomic token-use decrement; commit only on success, else rollback - parse_universe rebuilds its list instead of mutating while iterating - Data paths resolved via pathlib; deterministic synthetic sample data committed so /api/optimize works offline; dead yfinance code removed - Choropleth.jsx no longer re-downloads every 5s; broken auth redirects replaced with a shared login_required decorator Tooling: - pyproject on hatchling with audited deps + uv.lock; ruff replaces pylint/black; requirements.txt deleted - Frontend: webpack+babel -> Vite; pruned 17 unused deps (react-scripts, react-do, unused chart libs), added missing d3-scale, npm overrides dedupe vulnerable transitives (npm audit: 0); ESLint 9 flat config - Untracked var/michmoney.sqlite3 and build artifacts; removed 24 MB orphaned hero image and dead data files; rewritten .gitignore - GitHub Actions CI (uv+ruff+pytest, node eslint+vite), dependabot, MIT LICENSE, .editorconfig Tests and docs: - 76 pytest cases at 85% coverage: auth flows, CSRF (incl. non-ASCII), admin 403 matrix, /api/account (incl. non-ASCII key), optimizer end-to-end, timezone units - README rewritten with quickstart, scripts table, config + rotation warning, API docs, and structure; Devpost story preserved
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Real secrets were committed to this repo's history: the Flask
SECRET_KEY, three live admin API tokens, and real user accounts (emails + bcrypt hashes) insql/data.sqland the trackedvar/michmoney.sqlite3. This PR removes them from the tree, but they remain in git history — rotate them and treat the historical credentials as compromised.Summary
Full modernization of this SpartaHack fintech app (structurally a sibling of WolvWealth) to current professional standards, preserving app behavior.
Security
/api/admin/*and/api/db/*routes calledcheck_admin_priv()but discarded the result. New fail-closedrequire_adminreturns 403;db_dumpno longer returns password hashes or raw token valuesSECRET_KEYnow read fromMICHMONEY_SECRET_KEY(dev-only fallback + rotation warning); seed data replaced with obviously-fake dev accountsTypeErrorinsidehmac.compare_digest→ HTTP 500; now rejected cleanly as 403/400 (with regression tests)MAX_CONTENT_LENGTHrequest-body cap;bin/run prodruns gunicorn on localhost instead ofsudo flask --debugCorrectness
add_admin/remove_admin500'd on every request (phantomusernameparams)zoneinfoEastern time (unit-tested EST vs EDT)parse_universeno longer mutates the list it iteratespathlib; committed deterministic synthetic market data so/api/optimizeworks offline; dead/buggy yfinance code removedChoropleth.jsxno longer re-downloads its data every 5 seconds; brokenredirect(redirect(...))auth flows replaced with a sharedlogin_requireddecoratorTooling
pyproject.toml, audited deps,uv.lock; ruff replaces pylint/black; frozenrequirements.txtdeletedreact-scripts, typosquat-suspectreact-do, unused chart libs), added the genuinely-missingd3-scale, and used npmoverridesto dedupe vulnerable transitives —npm audit: 0 vulnerabilities. Charting libs actually in use (d3, visx, react-simple-maps, chart.js) were verified by import audit and kept. ESLint 9 flat config with react-hooks.gitignore.editorconfigTests & docs
/api/account(including non-ASCII key), optimizer end-to-end, timezone unitsVerification
uvinstall,ruff check/format --check,pytest(76/76),npm ci+ lint + Vite build,npm audit(0) — all greenGET /and/login/→ 200; auth-gated/forex/,/account/,/earnings-analyzer/→ 302; anonymousPOST /api/db/dump/→ 403; bundle asset served; no 500s in the log