Skip to content

fix: disable public Flask debug by default#4843

Open
JuanERombado wants to merge 2 commits into
Scottcjn:mainfrom
JuanERombado:codex/flask-debug-env-default
Open

fix: disable public Flask debug by default#4843
JuanERombado wants to merge 2 commits into
Scottcjn:mainfrom
JuanERombado:codex/flask-debug-env-default

Conversation

@JuanERombado
Copy link
Copy Markdown

Closes #4810
/claim #4810

Summary

  • Default the affected public Flask entrypoints to debug=False by deriving debug mode from FLASK_DEBUG instead of hard-coding debug=True.
  • Keep local development opt-in available with values like FLASK_DEBUG=1.
  • Add an AST regression test that fails if the listed public entrypoints bind 0.0.0.0 while hard-coding debug=True.

Security impact

Flask/Werkzeug debug mode is no longer enabled by default on helper services that bind to a public interface, reducing stack trace disclosure and debugger exposure risk if these scripts are run on a reachable host.

Validation

  • python -m pytest tests\test_public_flask_debug.py -q
  • python -m py_compile bcos_directory.py bridge\bridge_api.py contributor_registry.py explorer\app.py keeper_explorer.py security_test_payment_widget.py tests\test_public_flask_debug.py
  • git diff --check

Payout

RTC wallet: RTCd84b6e2d917d0272ecaae49f2f0dfe2f5474d585

@github-actions github-actions Bot added BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) BCOS-L2 Beacon Certified Open Source tier BCOS-L2 (required for non-doc PRs) security Security-related change tests Test suite changes labels May 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Welcome to RustChain! Thanks for your first pull request.

Before we review, please make sure:

  • Your PR has a BCOS-L1 or BCOS-L2 label
  • New code files include an SPDX license header
  • You've tested your changes against the live node

Bounty tiers: Micro (1-10 RTC) | Standard (20-50) | Major (75-100) | Critical (100-150)

A maintainer will review your PR soon. Thanks for contributing!

@JuanERombado
Copy link
Copy Markdown
Author

Payout wallet for this fix: RTCd84b6e2d917d0272ecaae49f2f0dfe2f5474d585

@github-actions github-actions Bot added the size/M PR: 51-200 lines label May 12, 2026
@JuanERombado
Copy link
Copy Markdown
Author

I do not have permission to apply repository labels. This security hardening PR should be labeled BCOS-L1 unless maintainers prefer BCOS-L2.

Copy link
Copy Markdown

@saim256 saim256 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functional direction looks good, but this currently fails the repo SPDX gate because the new test file has no license header.

Blocking issue:

  • tests/test_public_flask_debug.py is a new file and needs the standard SPDX header before it can pass tools/bcos_spdx_check.py.

Validation I ran locally:

  • git diff --check origin/main...HEAD -- bcos_directory.py bridge/bridge_api.py contributor_registry.py explorer/app.py keeper_explorer.py security_test_payment_widget.py tests/test_public_flask_debug.py -> passed
  • python -m py_compile bcos_directory.py bridge\bridge_api.py contributor_registry.py explorer\app.py keeper_explorer.py security_test_payment_widget.py tests\test_public_flask_debug.py -> passed, with an existing keeper_explorer.py invalid-escape warning
  • python -m pytest tests\test_public_flask_debug.py -q -> 1 passed, with the same existing keeper_explorer.py warning
  • python -m ruff check bcos_directory.py bridge\bridge_api.py contributor_registry.py explorer\app.py keeper_explorer.py security_test_payment_widget.py tests\test_public_flask_debug.py --select E9,F821,F811 --output-format=concise -> passed
  • python tools\bcos_spdx_check.py --base-ref origin/main -> failed: tests/test_public_flask_debug.py is missing an SPDX header

Adding # SPDX-License-Identifier: MIT at the top of the new test file should clear the blocker.

Copy link
Copy Markdown
Contributor

@508704820 508704820 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: Disable Public Flask Debug by Default

Summary

Changes all Flask app.run() calls from hardcoded debug=True to environment-controlled debug=FLASK_DEBUG. This prevents the Werkzeug debug console from being exposed on public interfaces (host='0.0.0.0').

What Works Well

  1. Critical security fix: Flask debug mode exposes an interactive Python console at /debugger, allowing remote code execution
  2. Consistent pattern: Same env var check across all files
  3. Multiple files fixed: bcos_directory.py, bridge_api.py, contributor_registry.py, explorer/app.py, faucet.py, profile_badge_generator.py, and more
  4. Default is safe: Without FLASK_DEBUG set, debug=False

Issues Found

1. High — host='0.0.0.0' still exposes the service publicly
Even with debug=False, binding to 0.0.0.0 makes the service accessible from any network interface. Combined with any future auth bypass or vulnerability, this is risky. Consider:

host = os.environ.get("FLASK_HOST", "127.0.0.1")  # Default to loopback only
app.run(debug=debug, host=host, port=5000)

2. Medium — No rate limiting on public endpoints
With host='0.0.0.0', any of these services are exposed without rate limiting. An attacker could brute-force the faucet, spam the contributor registry, or DDoS the explorer.

3. Low — FLASK_DEBUG env var is the standard Flask convention
Using the standard FLASK_DEBUG env var is correct and follows Flask conventions. Good.

Verdict: Approve — Critical security fix

This is an important fix. The host='0.0.0.0' concern is a separate issue but worth addressing.

Copy link
Copy Markdown
Contributor

@godd-ctrl godd-ctrl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes on current head be3398c.

The Flask debug behavior itself looks covered by the focused AST regression, but the PR currently fails the repository BCOS/SPDX gate because the new test file tests/test_public_flask_debug.py has no SPDX header.

Validation performed:

  • python -m pytest tests\test_public_flask_debug.py -q -> 1 passed, 1 warning
  • python -m py_compile bcos_directory.py bridge\bridge_api.py contributor_registry.py explorer\app.py keeper_explorer.py security_test_payment_widget.py tests\test_public_flask_debug.py -> passed with the pre-existing keeper_explorer.py invalid escape SyntaxWarning
  • git diff --check origin/main...HEAD -> passed
  • python tools\bcos_spdx_check.py --base-ref origin/main -> failed: missing SPDX header in tests/test_public_flask_debug.py
  • rg over the changed entrypoints found no remaining public app.run(... debug=True) literal after the patch

@JuanERombado
Copy link
Copy Markdown
Author

Addressed the SPDX blocker in commit c2532b8 by adding the required MIT SPDX header to tests/test_public_flask_debug.py. Re-ran: python -m pytest tests\test_public_flask_debug.py -q, python tools\bcos_spdx_check.py --base-ref origin/main, and git diff --check.

Copy link
Copy Markdown

@saim256 saim256 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved current head c2532b85a5a864141500b8cadfd889771405cb37 after the SPDX fix.

The public Flask debug hardening is now merge-ready in this focused scope: the affected app.run(host=0.0.0.0, ...) entrypoints no longer hard-code debug=True; debug mode is opt-in via FLASK_DEBUG, and the AST regression covers the public bind + hard-coded debug pattern.

Validation I ran locally:

  • git diff --check origin/main...HEAD -- bcos_directory.py bridge/bridge_api.py contributor_registry.py explorer/app.py keeper_explorer.py security_test_payment_widget.py tests/test_public_flask_debug.py -> passed
  • python -m py_compile bcos_directory.py bridge\bridge_api.py contributor_registry.py explorer\app.py keeper_explorer.py security_test_payment_widget.py tests\test_public_flask_debug.py -> passed, with the existing keeper_explorer.py invalid-escape warning
  • python tools\bcos_spdx_check.py --base-ref origin/main -> BCOS SPDX check: OK
  • python -m ruff check bcos_directory.py bridge\bridge_api.py contributor_registry.py explorer\app.py keeper_explorer.py security_test_payment_widget.py tests\test_public_flask_debug.py --select E9,F821,F811 --output-format=concise -> passed
  • python -m pytest tests\test_public_flask_debug.py -q -> 1 passed, same existing warning

I do not see a remaining blocker in this patch.

Copy link
Copy Markdown
Contributor

@508704820 508704820 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review — #4843

1. Critical security fix — debug mode disabled by default

Flask debug=True exposes the Werkzeug debugger, which allows arbitrary code execution via the interactive console. This is a well-known RCE vector. The fix correctly defaults to False.

2. Environment variable approach is good

Using FLASK_DEBUG env var follows Flask best practices and 12-factor app principles. The value check ({1, true, yes, on}) is comprehensive.

3. host='0.0.0.0' still exposes all interfaces

Even with debug=False, binding to 0.0.0.0 exposes the service on all network interfaces. In production, this should be 127.0.0.1 or behind a reverse proxy. Consider also making the host configurable via env var.

4. Multiple files fixed consistently

The PR applies the same fix to bcos_directory.py, bridge_api.py, and contributor_registry.py — consistent approach.

5. Positive

  • Debug-off-by-default is the correct production posture
  • Env var approach allows developers to enable debug in dev
  • No behavior change for developers who set FLASK_DEBUG=true

— Xeophon (security review)

Copy link
Copy Markdown

@dazer1234 dazer1234 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review for RustChain bounty #73.

Summary: This disables public Flask debug mode by default and uses an explicit truthy env parser. The AST test checks that 0.0.0.0 entrypoints do not hardcode debug=True.

Findings: No blocking issues found. The truthy set {1,true,yes,on} is clearer than a single-value check, and the regression test is less brittle than a string grep.

Verdict: Looks good. This overlaps with PR #4859, so only one of the duplicate fixes should be merged.

Reviewed with OpenAI Codex assistance.

Copy link
Copy Markdown
Contributor

@godd-ctrl godd-ctrl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved current head c2532b8.

The previous missing-SPDX blocker is fixed, and the public Flask entrypoints now derive debug from FLASK_DEBUG instead of hardcoding debug=True on 0.0.0.0 binds. Each touched file has os imported where needed and the focused AST regression covers the public entrypoints in this patch.

Validation performed:

  • git diff --name-status origin/main...HEAD -> six Flask entrypoints modified, tests/test_public_flask_debug.py added
  • git diff --check origin/main...HEAD -> passed
  • python tools\bcos_spdx_check.py --base-ref origin/main -> passed
  • python -m py_compile bcos_directory.py bridge\bridge_api.py contributor_registry.py explorer\app.py keeper_explorer.py security_test_payment_widget.py tests\test_public_flask_debug.py -> passed with pre-existing keeper_explorer invalid escape SyntaxWarning
  • python -m pytest tests\test_public_flask_debug.py -q -> 1 passed, same keeper_explorer warning
  • rg confirmed each touched entrypoint imports os and uses FLASK_DEBUG for app.run debug

No blocking issues found in the reviewed diff.

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great contribution! LGTM.

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great contribution! LGTM.

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great contribution! LGTM.

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great contribution! LGTM.

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great contribution! LGTM.

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great contribution! LGTM.

Copy link
Copy Markdown
Contributor

@jaxint jaxint left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great contribution! LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) BCOS-L2 Beacon Certified Open Source tier BCOS-L2 (required for non-doc PRs) security Security-related change size/M PR: 51-200 lines tests Test suite changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SECURITY] Public Flask entrypoints enable debug mode by default

6 participants