Skip to content

fix: close remaining multi-worker detection gaps - #449

Merged
AlexanderWagnerDev merged 9 commits into
mainfrom
bug-hunter-fix-20261103-0300
Nov 3, 2026
Merged

AlexanderWagnerDev merged 9 commits into
mainfrom
bug-hunter-fix-20261103-0300

Conversation

@AlexanderWagnerDev

@AlexanderWagnerDev AlexanderWagnerDev commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Close the remaining false negatives in the Gunicorn worker scanner that let an operator-supplied config run several workers while the login rate limiter stays per process:
    • dict mutator spellings reached through dict.__dict__ / globals().__class__.__dict__
    • map_async / starmap_async pool callbacks, ExitStack.push, and functools.partial thread targets and key= callbacks
    • class definitions inside if/try/with blocks (super chains, literal base tuples, constructor barriers, metaclasses, deferred type() constructors)
    • keyword-only heapq calls, dict(...) and named-__init__ type namespaces, nested def defaults, types.new_class(exec_body=...), and bare-name metaclasses
  • Remove the corresponding false positive where a safe constructor barrier inside a conditional block was rejected.
  • Treat every Gunicorn option that consumes the following token as value-taking, so --proxy-protocol/--http2-cleartext no longer swallow the app target.
  • Accept BOM-prefixed gunicorn.conf.py files in both the scanner and the entrypoint probe.

Verification

  • python -m pytest -m "not integration" — 1489 passed, 5 deselected (22 new regression tests)
  • python -c "import config, app, gunicorn_config_probe" — clean
  • python -m compileall — clean
  • sh entrypoint.sh stub check for --proxy-protocol/--http2-cleartext — default app target preserved

Play the walkthrough    Follow each request

Summary by CodeRabbit

  • Bug Fixes
    • Improved detection of Gunicorn worker settings changed through indirect mutations, callbacks, class definitions, and asynchronous operations.
    • Configuration files with a UTF-8 byte-order mark or Windows-style line endings are now handled correctly.
    • Command-line parsing recognizes additional Gunicorn options, handles optional values for --proxy-protocol, and no longer treats --wsgi-app as requiring a value.
  • Tests
    • Added regression coverage for configuration parsing and indirect worker-mutation detection.

- Recognize the remaining dict-mutator, pool/ExitStack/partial callback, conditional class, type()/new_class namespace and metaclass spellings in the Gunicorn worker scan.
- Keep the documented app target when value-taking gunicorn flags precede it.
- Accept a BOM-prefixed gunicorn config in both probe and scanner.
@coldtea-pr-lens

coldtea-pr-lens Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
  • Redraw · drawn at 015aab8, the branch has moved on

Architecture

Architecture diagram for OpenRTMP/librtmp2-server-panel at 015aab8

Play the walkthrough


Data flow

Data flow diagram for OpenRTMP/librtmp2-server-panel at 015aab8

Follow each request


Review

✨ Nothing flagged · reviewed 015aab8


Tip

Set hub.lumenfield.workment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture… row. Drawing still runs as before

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • Click the link under each diagram to open it on a canvas you can zoom, pan and step through
  • The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
  • Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works
  • After a push, tick Redraw to draw the latest commit
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion
  • Set github.description: false in .github/pr-lens.yml to stop PR Lens adding buttons to your PR descriptions

Thanks for using PR Lens! It's free for OSS. If it helped, a star helps other teams find it.  Star PR Lens on GitHub

@AlexanderWagnerDev

Copy link
Copy Markdown
Contributor Author

@codex review

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

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 26 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: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c7d9b865-587c-41fc-9956-a277ec3fbfb9
Commits

Reviewing files that changed from the base of the PR and between 7c83c60 and 7ed4db7.

Files selected for processing: 2
  • config.py
  • tests/test_gunicorn_indirect_workers_bypass.py
Walkthrough

The Gunicorn worker scanner now detects additional indirect mutations and import-time class effects. Configuration readers accept UTF-8 BOMs, and command-line parsing recognizes additional options that consume the next argument.

Changes: Gunicorn configuration analysis

Layer / File(s) Summary
Worker mutation paths
config.py, tests/test_gunicorn_indirect_workers_bypass.py
The scanner detects dictionary mutators accessed through class dictionaries, ExitStack callbacks, partial callbacks, asynchronous thread-pool maps, and heapq keyword callbacks. Regression tests cover these cases.
Import-time class and definition analysis
config.py, tests/test_gunicorn_indirect_workers_bypass.py
The scanner traverses compound import-time blocks and checks class construction, dynamic type initialization, metaclasses, and nested function definition-time effects. Tests cover conditional classes, dynamic types, and defaults.
Configuration input handling
config.py, gunicorn_config_probe.py, entrypoint.sh, tests/test_gunicorn_config_probe.py
Configuration readers use utf-8-sig to strip a UTF-8 BOM. Command-line parsing treats --proxy-protocol, --server-hooks, and --http2-* options as consuming the next argument. Tests cover BOM-prefixed and CRLF configuration files.

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix

Possibly related PRs

Merge Risk: Moderate · previous review 7c83c

Worker scanning can fail on supported Python 3.10 installations. Guard the version-specific AST reference before merging.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: closing remaining gaps in multi-worker detection.
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 4 functions across 4 files. (1 skipped: 1 too large.)

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • 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

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 889c191c-c4c7-470d-a92e-9237c69b7272
Commits

Reviewing files that changed from the base of the PR and between d78e7a8 and 7c83c60.

Files selected for processing: 2
  • config.py
  • tests/test_gunicorn_indirect_workers_bypass.py

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-03T14:17:26.034579Z f93afe7 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 015aab8e17

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread config.py Resolved
Comment thread config.py Resolved
Comment thread config.py Resolved
Comment thread config.py Resolved
Comment thread config.py Resolved
Comment thread config.py Resolved

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread config.py Resolved
Comment thread config.py Resolved
Comment thread config.py Resolved
Comment thread entrypoint.sh Resolved
- Keep every reachable literal base tuple when a conditional branch reassigns it.
- Do not record a calling lambda as a safe constructor barrier.
- Check ExitStack.push only through its exit hook and keep partial thread payloads.
- Separate new_class creation from instantiation and accept a positional exec_body.
- Handle unpacked heapq arguments and deferred annotations.
- Treat --proxy-protocol as an optional-value option so --config keeps its value.
… flag

- type(name, bases, ns) resolves a single literal namespace variable and stays static for a rebound one.
- --wsgi-app is no longer treated as a value-taking Gunicorn option (it does not exist in Gunicorn 26).

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread config.py Resolved
Comment thread config.py Resolved
@AlexanderWagnerDev

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f93afe704d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread config.py Resolved
Comment thread config.py Resolved
Comment thread config.py Resolved
Comment thread config.py Resolved
…tate

- A nested class that shares a module-level class name no longer rewrites that class's bases, hooks or metaclass: a bare name can never resolve to it.\n- A definite bases reassignment replaces the earlier tuple; only assignments inside a branch or loop are unioned.\n- A literal namespace is no longer trusted after del/update/pop/clear/|= mutation.\n- stack.push() only counts its exit hook when the stack actually unwinds.

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread config.py Resolved
The panel still supports Python 3.10, where ast.TryStar does not exist; referencing it directly raised AttributeError for any non-empty config. Look the newer node types up defensively and filter them out.
@sonarqubecloud

sonarqubecloud Bot commented Nov 3, 2026

Copy link
Copy Markdown

@AlexanderWagnerDev
AlexanderWagnerDev merged commit 6ce3dd9 into main Nov 3, 2026
12 checks passed
@AlexanderWagnerDev
AlexanderWagnerDev deleted the bug-hunter-fix-20261103-0300 branch November 3, 2026 17:52
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