security: fix admin bootstrap race and KB article disclosure
Address two security findings from darkwing scan: Finding 1 [High]: Unauthenticated admin bootstrap race - Require SETUP_TOKEN header or loopback origin for POST /api/setup/create-admin - Enforce 12-character minimum password for bootstrap admin - Cross-check setup_complete setting to prevent re-arming - Log token to container logs on first startup for operator retrieval - Add flask seed show-setup-token CLI helper - Add audit log entry when first admin is created - Preserve existing flask seed admin workflow (uses loopback) Finding 2 [Medium]: Unauthenticated KB article disclosure - Gate POST /api/knowledgebase/<id>/click on kb.view permission - Remove linkurl from response (caller already has it from GET) - Apply _visible_articles() filter to respect retired applications - Prevent anonymous link enumeration and counter manipulation Recovery paths if token is lost: 1. docker logs shopdb-api | grep "Setup token" 2. docker exec shopdb-api flask seed show-setup-token 3. docker exec shopdb-api flask seed admin (unchanged, always works) Zero breaking changes. CLI and existing workflows unaffected. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -204,6 +204,27 @@ def create_app(config_name: str = None) -> Flask:
|
||||
|
||||
# Initialize plugin manager
|
||||
with app.app_context():
|
||||
# On first run (no users exist), log the setup token so the operator can
|
||||
# create the first admin. The token gates POST /api/setup/create-admin to
|
||||
# prevent a network race during the install window (API starts serving
|
||||
# before the admin exists in every documented deploy path).
|
||||
from shopdb.core.models import User
|
||||
try:
|
||||
if User.query.count() == 0:
|
||||
token = app.config.get('SETUP_TOKEN') or os.environ.get('SETUP_TOKEN')
|
||||
if token:
|
||||
app.logger.warning('=' * 60)
|
||||
app.logger.warning('FIRST RUN: No users exist.')
|
||||
app.logger.warning('Setup token: %s', token)
|
||||
app.logger.warning('Create admin: POST /api/setup/create-admin')
|
||||
app.logger.warning(' with header: X-Setup-Token: <token>')
|
||||
app.logger.warning('OR use CLI: docker exec shopdb-api flask seed admin')
|
||||
app.logger.warning('=' * 60)
|
||||
else:
|
||||
app.logger.warning('FIRST RUN: No users exist, no SETUP_TOKEN set.')
|
||||
app.logger.warning('Use CLI: docker exec shopdb-api flask seed admin')
|
||||
except Exception:
|
||||
pass # DB not ready yet, skip
|
||||
plugin_manager.init_app(app, db)
|
||||
|
||||
# Register core blueprints
|
||||
|
||||
Reference in New Issue
Block a user