Skip to content

fix(security): sanitize global 500 exception handler (CWE-209) — minimal, single-sink - #842

Merged
groupthinking merged 2 commits into
mainfrom
claude/determined-maxwell-ibuhoc
Jul 17, 2026
Merged

fix(security): sanitize global 500 exception handler (CWE-209) — minimal, single-sink#842
groupthinking merged 2 commits into
mainfrom
claude/determined-maxwell-ibuhoc

Conversation

@groupthinking

Copy link
Copy Markdown
Owner

Summary

Closes the one HTTP-500 information-disclosure sink (CWE-209) still live on main: the global Exception handler in backend/main.py. On any unhandled error it returned a JSONResponse whose body echoed str(exc), exc.__class__.__name__, and str(request.url) to the client.

The per-route HTTPException(status_code=500, detail=...) sinks were already sanitized on main. This handler is different: it leaks via JSONResponse(status_code=500, content={...}).

Why this leak survived ~15 green PRs (root cause)

The repo currently has a cluster of ~15 open PRs all attempting the same 500-hardening (#804, #807, #810, #814#821, #826, #827, #831, #832, #834), each claiming to be "the consolidation." Every one passed the guard tests/unit/test_500_info_disclosure.py — yet the leak persisted. The reason is a structural blind spot in that guard:

  1. It only inspects HTTPException(...) calls; it never looks at the JSONResponse(status_code=500, content=...) form the global handler uses.
  2. main.py isn't even in its _GUARDED_FILES tuple.

So the guard is structurally incapable of seeing this sink. That is why the cluster kept regenerating without ever fixing the actual remaining leak.

Changes (2 files)

  • backend/main.pyglobal_exception_handler now returns a static body {"error"/"detail": "Internal server error", "timestamp"}. The exception (type, message, traceback) and request path are logged server-side only via logger.error(..., exc_info=True). The 4xx ValueError handler is intentionally left unchanged (4xx echoes client-supplied input, not an internal-disclosure vector).
  • tests/unit/test_backend_main.py — replaces the two tests that asserted the leaky contract (error_type, version) with regression guards that exercise the handler and prove the 500 body is static and never echoes the exception message, class name, or request URL.

Verification

pytest/fastapi are not installable in the ephemeral session sandbox without pulling the heavy google-cloud/ML stack, so this was verified by exercising the real handler source directly (extracted via AST, executed against a stub JSONResponse/logger):

  • 500 body contains no exception text, class name, or URL — while the full error is still logged server-side.
  • The no-.url request path does not crash.
  • The ValueError handler still returns 400.

Relationship to the duplicate cluster

This is deliberately minimal and merge-clean on current main (single production file, 2 files total), unlike the cluster: e.g. #834 targets the same handler but is now mergeable_state: dirty (conflicted) and touches 9 files. Recommendation for the maintainer: land this, then close the redundant cluster (#804, #807, #810, #814#821, #826, #827, #831, #832, #834). A follow-up could widen the AST guard to cover the JSONResponse 500 form and add main.py to _GUARDED_FILES so this class of sink can't hide again.

Left as draft — targets protected main; not auto-merged.

🤖 Generated with Claude Code

https://claude.ai/code/session_016kZayBH8HUEt4ys7ofaH52


Generated by Claude Code

The global `Exception` handler in `backend/main.py` was the one HTTP-500
information-disclosure sink still live on `main`: its JSONResponse body echoed
`str(exc)`, `exc.__class__.__name__`, and `str(request.url)` to the client on
any unhandled error. The per-route `HTTPException(500, ...)` sinks were already
sanitized, but this handler leaked via `JSONResponse(status_code=500, content=...)`.

That call form is exactly what the existing AST guard
(`tests/unit/test_500_info_disclosure.py`) does not inspect — it only scans
`HTTPException(...)` calls, and `main.py` is not in its `_GUARDED_FILES` — which
is why the leak survived every green CI run.

Changes:
- `global_exception_handler` now returns a static body
  (`{"error"/"detail": "Internal server error", "timestamp"}`); the exception
  (type, message, traceback) and request path are logged server-side only via
  `exc_info=True`. The 4xx `ValueError` handler is intentionally left unchanged.
- Replace the two `test_backend_main.py` tests that asserted the leaky contract
  (`error_type`, `version`) with regression guards proving the 500 body is static
  and never echoes the exception message, class name, or request URL.

Verified by exercising the real handler source directly (pytest/fastapi are not
installable in the ephemeral sandbox without the heavy ML stack): the 500 body
contains no exception text, class name, or URL, while the full error is still
logged; the no-`.url` path is safe; the 400 handler still returns 400.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kZayBH8HUEt4ys7ofaH52
@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v0-uvai Ready Ready Preview, Comment, Open in v0 Jul 17, 2026 8:23am

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 6456ba1.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Scanned Files

None

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • [‘architecture-gap’, ‘bug’, ‘ci-cd’, ‘ci/cd’, ‘copilot-rabbit’, ‘documentation’, ‘duplicate’, ‘enhancement’, ‘frontend’, ‘github_actions’, ‘good first issue’, ‘help wanted’, ‘high-priority’, ‘invalid’, ‘javascript’, ‘ml-model’, ‘needs-triage’, ‘pipeline-critical’, ‘placeholder-code’, ‘priority:high’, ‘python’, ‘python:uv’, ‘question’, ‘styling’, ‘tests’, ‘v0’]

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: a0f886f6-9337-4f3e-8627-7004b1679e90

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The global exception handler now logs request URLs and full tracebacks server-side while returning a static generic 500 JSON response without exception or environment details.

Changes

Exception handling

Layer / File(s) Summary
Generic error response
src/youtube_extension/backend/main.py
The global exception handler retains server-side traceback logging and returns only generic error fields plus a timestamp, removing client-visible exception, request, and environment metadata.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: security

Poem

Exceptions whisper, safely out of sight,
Logs hold the clues through the night.
Clients see a message plain,
No stack traces spill like rain.
A timestamp marks the guarded flight.

🚥 Pre-merge checks | ✅ 5 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Enforce Copilot Verification ⚠️ Warning No PR-specific Copilot approval evidence found; GitHub Copilot code review is comment-only and cannot supply an approving review. Request Copilot code review and record its comment review, or change the gate to accept Copilot-reviewed comments instead of approval.
Require Ai Unit Tests ⚠️ Warning PR #842 has python/security/tests labels, but copilot-rabbit is missing; tests/unit/test_backend_main.py was updated, but the required label isn't present. Add the copilot-rabbit label (or change the gate) and keep the unit-test update in the same PR before merge.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: hardening the global 500 handler against information disclosure.
Description check ✅ Passed The description matches the patch by describing the sanitized global 500 handler and the regression tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/determined-maxwell-ibuhoc
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/determined-maxwell-ibuhoc

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Owner Author

@coderabbitai review


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== PR metadata and diff ==='
gh pr view 842 --json number,title,state,isDraft,baseRefName,headRefName,files --jq \
  '{number,title,state,isDraft,baseRefName,headRefName,files:[.files[].path]}'
gh pr diff 842 -- backend/main.py tests/unit/test_backend_main.py

echo '=== backend/main.py outline ==='
ast-grep outline backend/main.py --items all --type function,class --view expanded || true

echo '=== test_backend_main.py outline ==='
ast-grep outline tests/unit/test_backend_main.py --items all --type function,class --view expanded || true

echo '=== exception handlers and response conventions ==='
rg -n -C 8 \
  '@.*exception_handler|def global_exception_handler|def .*exception_handler|JSONResponse\(|HTTPException\(' \
  backend/main.py tests/unit/test_backend_main.py

Length of output: 1520


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== PR diff ==='
gh pr diff 842

echo '=== Production file outline ==='
ast-grep outline src/youtube_extension/backend/main.py --items all --type function,class --view expanded || true

echo '=== Test file outline ==='
ast-grep outline tests/unit/test_backend_main.py --items all --type function,class --view expanded || true

echo '=== Relevant handlers and tests ==='
rg -n -C 10 \
  '@.*exception_handler|def global_exception_handler|def .*exception_handler|JSONResponse\(|HTTPException\(|global_exception_handler|ValueError' \
  src/youtube_extension/backend/main.py tests/unit/test_backend_main.py

Length of output: 29358


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== main imports and error-handler region ==='
sed -n '1,100p' src/youtube_extension/backend/main.py
sed -n '430,478p' src/youtube_extension/backend/main.py

echo '=== Logging configuration and remote log sinks ==='
rg -n -i -C 4 \
  'basicConfig|dictConfig|FileHandler|StreamHandler|CloudLogging|google\.cloud\.logging|LoggingHandler|loguru|sentry|logger\s*=|getLogger' \
  src tests pyproject.toml requirements*.txt 2>/dev/null || true

echo '=== Sensitive query parameters and request URL logging ==='
rg -n -i -C 3 \
  '(query|Query)\([^)]*(token|key|secret|password|credential|auth)|[?&](token|key|secret|password|credential|auth)=|request\.url|url\.query|query_params' \
  src/youtube_extension tests 2>/dev/null || true

echo '=== Handler tests and logger assertions ==='
sed -n '555,632p' tests/unit/test_backend_main.py
rg -n -C 3 'global_exception_handler|Unhandled exception on|assert.*logger|mock.*logger' \
  tests src/youtube_extension 2>/dev/null || true

Length of output: 208766


@groupthinking I found one blocking security regression:

  • High — full request URLs, including query-string secrets, are now written to Cloud Run logs. At Line 462 and Line 464 in src/youtube_extension/backend/main.py, str(request.url) is included in the error message. This service explicitly streams logs to stdout for Cloud Run, so a failing request such as ...?token=abc persists that token in centralized logs. The new test already demonstrates this input but only asserts that it is absent from the response.

    Log only the route path (for example, request.url.path) and method, never the complete URL/query string. Add a regression assertion that the logger call does not contain token=abc while preserving exc_info=True.

The client-facing 500 response sanitization itself is correct: exception messages, class names, and the request URL are no longer returned to callers.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…dler

Addresses CodeRabbit review on #842: the previous commit's log line used
`str(request.url)`, which includes the query string. Since the service streams
logs to stdout for Cloud Run, a failing request like `...?token=abc` would
persist that secret in centralized logs (a server-side variant of the same
CWE-209 concern).

- `global_exception_handler` now logs `request.url.path` and the HTTP method
  only — never the full URL/query string. `exc_info=True` is preserved so the
  traceback is still captured.
- Add `test_global_exception_handler_log_omits_query_string`: asserts the logger
  call omits a `?token=SECRET123` query secret, still records the bare path, and
  keeps `exc_info=True` — guarding against a regression to `str(request.url)`.

Verified against the real handler source (fastapi/pytest unavailable in the
sandbox): log line contains the path but not the token; body remains static;
the no-`.url` path and the 400 `ValueError` handler are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016kZayBH8HUEt4ys7ofaH52

Copy link
Copy Markdown
Owner Author

@coderabbitai Good catch — fixed in 6456ba1. The global handler now logs only request.url.path and the HTTP method, never str(request.url), so query-string secrets (e.g. ?token=...) no longer reach the Cloud Run logs. exc_info=True is preserved for the traceback. Added test_global_exception_handler_log_omits_query_string, which asserts a ?token=SECRET123 value is absent from the logger call while the bare path is still recorded and exc_info=True is kept — guarding against a regression to str(request.url).


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@groupthinking Confirmed—this addresses the reported log disclosure risk. Logging only the HTTP method and request.url.path, with a regression test excluding query-string secrets and retaining exc_info=True, prevents tokens in failing request URLs from reaching Cloud Run logs.

🐇 ✅

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/youtube_extension/backend/main.py`:
- Around line 456-465: Update the unhandled-exception logging around
request_path to record only the HTTP method and URL path, excluding query
parameters, while retaining exc_info=True. Revise the surrounding docstring to
describe the sanitized log data, and add a regression test asserting query
values are absent from the log and exception information remains enabled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro

Run ID: 44cab5bc-f2d6-445e-a11a-e0c6f249d7eb

📥 Commits

Reviewing files that changed from the base of the PR and between b779484 and 93bceeb.

⛔ Files ignored due to path filters (1)
  • tests/unit/test_backend_main.py is excluded by !tests/**
📒 Files selected for processing (1)
  • src/youtube_extension/backend/main.py
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • groupthinking/uvai-skills (manual)
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{py,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{py,js,jsx,ts,tsx}: Use Python 3.9+ and Node 18+ for development
Never hardcode API keys, database URLs, or secrets in code
Make minimal, surgical changes and avoid deleting working code unless fixing security issues

Files:

  • src/youtube_extension/backend/main.py
**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.py: Always use type hints for Python functions
Use Black formatter with 88 character line length for Python code
Follow PEP 8 conventions for Python code
Use descriptive variable names and add docstrings to all public functions in Python
Group imports in Python: standard library, third-party, local
Use SQLAlchemy ORM and never write raw SQL queries
Use environment variables via os.getenv() or pydantic-settings to access configuration
Wrap database operations in try-except blocks and use context managers or FastAPI dependencies for connection cleanup
Implement comprehensive error handling with proper logging in all functions
Version APIs using /api/v1/ prefix for stability
Use JSON-RPC 2.0 protocol for all MCP communication
Follow the single-flow workflow: YouTube link → context extraction → agent dispatch → outputs
Use context managers for resource management in Python code
Implement comprehensive input validation and sanitize outputs for security
Use parameterized queries and SQLAlchemy ORM to prevent SQL injection
Define API request/response models using Pydantic for FastAPI endpoints
Store the single unified workflow as the only workflow; never introduce alternate flows or manual triggers
Use SQLAlchemy with connection pooling for database connections and manage sessions with context managers
Provide sensible defaults for non-sensitive configuration in Python settings
Maintain backward compatibility and do not break existing API endpoints
Include comprehensive logging for debugging in MCP implementations

**/*.py: Format Python code with Black using an 88-character line length.
Use Ruff with rules E, W, F, I, B, C4, and UP; E501 is ignored.
Use strict mypy checking with untyped function definitions disallowed.

Files:

  • src/youtube_extension/backend/main.py

⚙️ CodeRabbit configuration file

Python backend code. Check for type hints, proper exception handling, async context manager usage, and potential blocking calls in async functions. Flag any bare except clauses or missing timeout parameters on network calls. CRITICAL: Flag any file that contains placeholder/stub implementations — especially in unified_ai_sdk. Any class or function that says "TODO: Replace with production implementation" or returns mock/fake data must be flagged as a blocking issue. Flag any code generation output that reaches users without AST validation or syntax checking.

Files:

  • src/youtube_extension/backend/main.py
**/*.{py,js,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Maintain >80% code coverage for new features

Files:

  • src/youtube_extension/backend/main.py
**/*.{py,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{py,ts,tsx}: Keep frontend and backend data models synchronized using matching Pydantic (backend) and TypeScript (frontend) interfaces
Use type-safe interfaces for backend-frontend data exchange

Files:

  • src/youtube_extension/backend/main.py
**/*

📄 CodeRabbit inference engine (Custom checks)

**/*: Strictly verify that GitHub Copilot has explicitly reviewed and approved the pull request; human approvals alone must not satisfy this check.
Before allowing a merge, require the copilot-rabbit label and AI-generated unit tests committed alongside the code changes; fail the check if either is missing.

**/*: Follow the documented event naming convention <domain>.<entity>.<action>, such as youtube.video.captured.
Use the service-container dependency injection pattern for backend dependencies.
Never infer SDK types from tests or API documentation alone; use backend response models as the authority.
When auditing branches, use the branch-cleanup skill and its six-gate fail-test harness; archive branches with git tag archive/<branch> before deletion, and do not rely on three-dot diffs or git merge-tree for orphaned branches.

For Vercel-specific work, include https://vercel.com/docs/llms-full.txt in the AI assistant context set.

Files:

  • src/youtube_extension/backend/main.py
src/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.py: Format Python code with Black using an 88-character line length.
Sort Python imports with isort using the Black profile.
Use Ruff with E, W, F, I, B, C4, and UP rules; E501 is ignored.
Use mypy strict mode; untyped function definitions are disallowed.
Target Python 3.9 or newer.
Validate backend inputs with Pydantic and sanitize subprocess arguments.
Maintain strict mypy type safety in the Python backend.
Use the required Anthropic SDK parameters thinking={"type": "adaptive"} and output_config={"effort": "..."} with the current model string claude-opus-4-8; do not add TypeError compatibility fallbacks.

src/**/*.py: Do not introduce alternative workflows or manual triggers that bypass the single YouTube link → transcript → events → agents → outputs pipeline.
Use event names in the <domain>.<entity>.<action> format.
Use the service-container dependency-injection pattern for dependencies.
Use Pydantic input validation and sanitize subprocess arguments.
Production code must use real behavior only; do not add mock delays or fake data.

Files:

  • src/youtube_extension/backend/main.py
**/*.{py,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{py,ts,tsx,js,jsx}: Do not use mock delays, fake data, or simulated responses in production code; production must remain REAL_MODE_ONLY.
Do not hard-code secrets, keys, or credentials; store them in .env files that are gitignored.

Do not include secrets or API keys in source code; load them from environment variables instead.

Files:

  • src/youtube_extension/backend/main.py
**/*.{py,pyw}

📄 CodeRabbit inference engine (AGENTS.md)

Write Python code to remain compatible with Linux and Windows where possible, including correct handling of asyncio event loops.

Files:

  • src/youtube_extension/backend/main.py
🔍 Remote MCP GitHub Copilot
  • PR #842 is open and draft, with 2 files changed (+35/−21). It targets the remaining JSONResponse-based global 500 sink; the per-route HTTPException(500, ...) sinks were already sanitized. Vercel checks are successful, while CodeRabbit review is still pending.
  • In src/youtube_extension/backend/main.py, the global Exception handler now returns a static 500 body (error/detail/timestamp) and logs server-side with exc_info=True. The file also configures logging to StreamHandler(sys.stdout), and the current log message still interpolates str(request.url) via request_path, so full URLs/query strings can still reach logs. The ValueError 400 handler is unchanged and still echoes str(exc) plus path.
  • tests/unit/test_backend_main.py now checks that the 500 response does not leak exception type, exception message, or request URL, and that the handler does not crash when request.url is missing.
  • CodeRabbit’s main blocking comment is that logging the full request URL can expose query-string secrets (example: token=abc) in Cloud Run logs; it recommends logging only path/method and asserting the logger call omits sensitive params while keeping exc_info=True. It also notes its automated review skipped tests/unit/test_backend_main.py because of the !tests/** path filter.
  • Dependency Review reported no vulnerabilities, no license issues, and no OpenSSF Scorecard issues; it also warned that no snapshots were found for the head SHA.

Comment thread src/youtube_extension/backend/main.py
@groupthinking
groupthinking requested a review from Copilot July 17, 2026 08:26
@linear-code
linear-code Bot marked this pull request as ready for review July 17, 2026 08:26

Copy link
Copy Markdown
Owner Author

@coderabbitai resolve

The changes_requested review and the inline Line 465 comment both reviewed commit 93bceeb (the pre-fix commit). The full-URL logging finding is already fixed in 6456ba1: the handler now logs request.url.path + HTTP method (never str(request.url)), keeps exc_info=True, and a new regression test (test_global_exception_handler_log_omits_query_string) asserts a ?token=SECRET123 value is absent from the logger call. CodeRabbit already confirmed this fix in its follow-up reply.


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@groupthinking Confirmed. The full-URL logging issue was addressed in 6456ba1, including the regression coverage for query-string secrets and preservation of exc_info=True. Resolving the prior review findings.

✅ Action performed

Comments resolved and changes approved.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Sanitizes the global FastAPI 500 handler to prevent internal error disclosure while preserving server-side diagnostics.

Changes:

  • Replaces dynamic 500 response details with generic messages.
  • Logs exception context without query strings.
  • Adds regression tests for response and log sanitization.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/youtube_extension/backend/main.py Sanitizes global 500 responses and logging.
tests/unit/test_backend_main.py Verifies exception details and URLs are not exposed.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants