Skip to content

fix(security): sanitize user-controlled values in API logs (CWE-117 log injection) - #810

Open
groupthinking wants to merge 4 commits into
mainfrom
claude/determined-maxwell-raq7mg
Open

fix(security): sanitize user-controlled values in API logs (CWE-117 log injection)#810
groupthinking wants to merge 4 commits into
mainfrom
claude/determined-maxwell-raq7mg

Conversation

@groupthinking

@groupthinking groupthinking commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Canonical issue

Closes #913. Progresses #898.

Outcome

Prevent CWE-117 log forging by stripping CR/LF from every verified user-controlled value interpolated into v1-router logs.

Scope

  • src/youtube_extension/backend/api/v1/router.py
  • tests/unit/test_v1_router_extended.py

Risk

Sanitization intentionally changes only logged representations. Request values and application behavior remain unchanged.

Verification

  • Exact head: d0d4b9844c00e8a7b15c99a6a70cbda554a9d648; main + one commit, behind 0, mergeable.
  • _safe_log() is applied at all 14 verified sinks; focused test suite: 123 passed.
  • Security Scan 29813525434, Coverage 29813525568, CodeQL 29813525507, CI 29813525515, Dependency Review 29813525500, and Secret Scan 29813525542 passed; E2E 29813525535 was repository-skipped.
  • 0 unresolved review threads. Copilot reviewed 2/2 changed files on the exact head at 2026-07-21T08:55:53Z and produced no findings.

Production evidence

  • Exact-head Vercel Preview dpl_Fdpn7bMnQw7CWh9MXfo6BtLzjunh is READY and commit-verified.
  • Vercel builds the Next.js apps/web root; this Python-only change is not exercised by the Preview. It proves web compatibility, not Python runtime behavior.
  • Vercel production remains READY with no runtime error clusters in the preceding 24 hours.

Proven provenance blocker

Mutable identity/linkage fields are repaired. Truth-gate rerun 29816054127 now projects claude / #913 / session_01FZcDgrGTkknC2ya13Uy6bU correctly; it remains blocked on missing frozen pre-dispatch intent and a trusted terminal agent result. Because #810 predates #913, keep draft and do not weaken or impersonate the gate.

Draft exit checklist

  • One focused child issue and one canonical PR.
  • Current-main refresh.
  • Focused tests and exact-head workflows.
  • Zero unresolved threads.
  • Exact-head Preview classified.
  • copilot-rabbit present; Copilot reviewed 2/2 changed files on the exact head with no findings.
  • Valid historical provenance disposition and trusted agent result.
  • Final human review.

Execution receipt

  • Agent login: claude
  • Agent run ID: session_01FZcDgrGTkknC2ya13Uy6bU
  • Canonical branch: claude/determined-maxwell-raq7mg
  • Exact head: d0d4b9844c00e8a7b15c99a6a70cbda554a9d648

@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, v0 Aug 2, 2026 4:31pm

@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 80add3e.
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 Plus

Run ID: f2f7e968-511d-4315-a80b-aac66327904c

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

Changes

Log Sanitization

Layer / File(s) Summary
Sanitize interpolated log values
src/youtube_extension/backend/api/v1/router.py
Adds _safe_log() to remove carriage returns and newlines, then applies it to identifiers in chat, video-processing, action, and video-job log messages.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested labels: security

Suggested reviewers: claude

Poem

Newlines tried to split the trail,
Safe logs now hold the rail.
IDs pass clean,
In every routine,
No forged entries prevail.

🚥 Pre-merge checks | ✅ 5 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Enforce Copilot Verification ⚠️ Warning No explicit Copilot approval exists for PR #810; retrieved PR data shows zero reviews and no Copilot review comments. Request an explicit GitHub Copilot review/approval on the PR. Human approvals or comments do not satisfy this check.
Require Ai Unit Tests ⚠️ Warning PR #810 adds TestSafeLog regression tests, but PR metadata shows the required copilot-rabbit label is missing. Add the copilot-rabbit label to PR #810 and re-run the check; the unit tests are already committed in tests/unit/test_v1_router_extended.py.
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly matches the main change: sanitizing user-controlled log values to prevent log injection.
Description check ✅ Passed The description covers summary, linked issue, verification, and provenance, though it uses different headings than the template.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/determined-maxwell-raq7mg
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/determined-maxwell-raq7mg

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

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

@groupthinking: Reviewing the changes in #810 now.

✅ 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.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/youtube_extension/backend/api/v1/router.py (1)

606-622: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Sanitize the remaining raw identifier interpolations.

Line 612 still logs video_id directly, so a CR/LF payload in ChatRequest.video_id can forge additional log entries despite the surrounding fixes. Also, _run_video_job still logs raw job_id in the missing-job branch at Line 1519. Apply _safe_log() to both paths.

Proposed fix
-                    f"Video not found for {video_id}, triggering real-time processing"
+                    f"Video not found for {_safe_log(video_id)}, triggering real-time processing"

-        logger.error("Video job %s missing at run time", job_id)
+        logger.error("Video job %s missing at run time", _safe_log(job_id))

Also applies to: 1565-1565

🤖 Prompt for 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.

In `@src/youtube_extension/backend/api/v1/router.py` around lines 606 - 622,
Update the logging statements in the video-not-found processing path and the
missing-job branches of _run_video_job to pass video_id and job_id through
_safe_log() before interpolation. Preserve the existing log messages and
behavior while ensuring all referenced identifier values are sanitized.
🤖 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.

Outside diff comments:
In `@src/youtube_extension/backend/api/v1/router.py`:
- Around line 606-622: Update the logging statements in the video-not-found
processing path and the missing-job branches of _run_video_job to pass video_id
and job_id through _safe_log() before interpolation. Preserve the existing log
messages and behavior while ensuring all referenced identifier values are
sanitized.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4487a95c-7662-4a44-af24-00258ce81fa6

📥 Commits

Reviewing files that changed from the base of the PR and between 6aa90db and 9212e6f.

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

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

  • groupthinking/uvai-skills (manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: test
⚠️ CI failures not shown inline (4)

GitHub Actions: Security Scan / trivy: fix(security): sanitize user-controlled values in API logs (CWE-117 log injection)

Conclusion: failure

View job details

##[group]Run entrypoint.sh
 �[36;1mentrypoint.sh�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CODEQL_ACTION_FEATURE_MULTI_LANGUAGE: false
   CODEQL_ACTION_FEATURE_SANDWICH: false
   CODEQL_ACTION_FEATURE_SARIF_COMBINE: true
   CODEQL_ACTION_FEATURE_WILL_UPLOAD: true
   CODEQL_ACTION_VERSION: 4.37.1
   CODEQL_ACTION_ANALYSIS_KEY: .github/workflows/security.yml:trivy
   CODEQL_WORKFLOW_STARTED_AT:
   CODEQL_ACTION_JOB_STATUS: JOB_STATUS_CONFIGURATION_ERROR
   INPUT_SCAN_TYPE: image
   INPUT_IMAGE_REF: eventrelay:test
   INPUT_SCAN_REF: .
   INPUT_TRIVYIGNORES: .trivyignore
   INPUT_GITHUB_PAT:
   INPUT_LIMIT_SEVERITIES_FOR_SARIF:
   TRIVY_CACHE_DIR: /home/runner/work/EventRelay/EventRelay/.cache/trivy
 ##[endgroup]
 Found ignorefile '.trivyignore':
 # Trivy Ignore File
 # This file contains vulnerabilities that are accepted risks or false positives
 # Format: CVE-ID or vulnerability ID, one per line
 # Comments start with #
 # Go crypto certificate validation issues in base images
 # These are typically fixed by updating the base image in future releases
 # and are not directly actionable in application code
 CVE-2025-58183
 CVE-2025-61729
 # Add other CVEs here as needed with justification comments
 Running Trivy with options: trivy image eventrelay:test
 	INFO	[vuln] Vulnerability scanning is enabled
 	INFO	[secret] Secret scanning is enabled
 	INFO	[secret] If your scanning is slow, please try '--scanners vuln' to disable secret scanning
 	INFO	[secret] Please see https://trivy.dev/docs/v0.70/guide/scanner/secret#recommendation for faster secret detection
 📣 �[34mNotices:�[0m
   - Version 0.72.0 of Trivy is now available, current version is 0.70.0
 To suppress version checks, run Trivy scans with the --skip-version-check flag
 	FATAL	Fatal error	run error: image scan error: scan error: unable to initialize a scan service: unable to initialize artifact: unable to initialize container image: unable to find the specified image "eventrel...

GitHub Actions: Security Scan / trivy: fix(security): sanitize user-controlled values in API logs (CWE-117 log injection)

Conclusion: failure

View job details

##[group]Run github/codeql-action/upload-sarif@v4
 with:
   sarif_file: trivy-results.sarif
   checkout_path: /home/runner/work/EventRelay/EventRelay
   ***REDACTED***
   matrix: null
   wait-for-processing: true
 ##[endgroup]
 ##[error]Path does not exist: trivy-results.sarif

GitHub Actions: Security Scan / 2_trivy.txt: fix(security): sanitize user-controlled values in API logs (CWE-117 log injection)

Conclusion: failure

View job details

4-3) ...
 `#9` 24.28 Setting up libisl23:amd64 (0.27-1) ...
 `#9` 24.28 Setting up libc-dev-bin (2.41-12+deb13u3) ...
 `#9` 24.29 Setting up libx265-215:amd64 (4.1-2) ...
 `#9` 24.29 Setting up libsamplerate0:amd64 (0.2.2-4+b2) ...
 `#9` 24.29 Setting up libwebpmux3:amd64 (1.5.0-0.1) ...
 `#9` 24.29 Setting up libdrm-common (2.4.124-2) ...
 `#9` 24.30 Setting up libjxl0.11:amd64 (0.11.2-0.1~deb13u2) ...
 `#9` 24.30 Setting up libxml2:amd64 (2.12.7+dfsg+really2.9.14-2.1+deb13u3) ...
 `#9` 24.30 Setting up libcc1-0:amd64 (14.2.0-19) ...
 `#9` 24.31 Setting up libldap2:amd64 (2.6.10+dfsg-1) ...
 `#9` 24.31 Setting up libzvbi-common (0.2.44-1) ...
 `#9` 24.31 Setting up liblsan0:amd64 (14.2.0-19) ...
 `#9` 24.31 Setting up libmp3lame0:amd64 (3.100-6+b3) ...
 `#9` 24.32 Setting up libitm1:amd64 (14.2.0-19) ...
 `#9` 24.32 Setting up libvorbisenc2:amd64 (1.3.7-3) ...
 `#9` 24.33 Setting up libdvdnav4:amd64 (6.1.1-3+b1) ...
 `#9` 24.33 Setting up libiec61883-0:amd64 (1.2.0-7) ...
 `#9` 24.34 Setting up libserd-0-0:amd64 (0.32.4-1) ...
 `#9` 24.34 Setting up libxkbcommon0:amd64 (1.7.0-2) ...
 `#9` 24.34 Setting up libwayland-client0:amd64 (1.23.1-3) ...
 `#9` 24.34 Setting up libctf0:amd64 (2.44-3) ...
 `#9` 24.35 Setting up libksba8:amd64 (1.6.7-2+b1) ...
 `#9` 24.35 Setting up pinentry-curses (1.3.1-2) ...
 `#9` 24.36 Setting up libavc1394-0:amd64 (0.5.4-5+b2) ...
 `#9` 24.36 Setting up libxcb-dri3-0:amd64 (1.17.0-2+b1) ...
 `#9` 24.36 Setting up libllvm19:amd64 (1:19.1.7-3+b1) ...
 `#9` 24.36 Setting up libx11-xcb1:amd64 (2:1.8.12-1) ...
 `#9` 24.37 Setting up liblapack3:amd64 (3.12.1-6) ...
 `#9` 24.37 update-alternatives: using /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3 to provide /usr/lib/x86_64-linux-gnu/liblapack.so.3 (liblapack.so.3-x86_64-linux-gnu) in auto mode
 `#9` 24.37 Setting up gpg-agent (2.4.7-21+deb13u1+b4) ...
 `#9` 24.80 Setting up libcaca0:amd64 (0.99.beta20-5+deb13u1) ...
 `#9` 24.81 Setting up libzvbi0t64:amd64 (0.2.44-1) ...
 `#9` 24.81 Setting up libxrender1:amd64 (1:0.9.12-1) ...
 `#9` 24.81 Setting up lib...

GitHub Actions: Security Scan / trivy: fix(security): sanitize user-controlled values in API logs (CWE-117 log injection)

Conclusion: failure

View job details

4-3) ...
 `#9` 24.28 Setting up libisl23:amd64 (0.27-1) ...
 `#9` 24.28 Setting up libc-dev-bin (2.41-12+deb13u3) ...
 `#9` 24.29 Setting up libx265-215:amd64 (4.1-2) ...
 `#9` 24.29 Setting up libsamplerate0:amd64 (0.2.2-4+b2) ...
 `#9` 24.29 Setting up libwebpmux3:amd64 (1.5.0-0.1) ...
 `#9` 24.29 Setting up libdrm-common (2.4.124-2) ...
 `#9` 24.30 Setting up libjxl0.11:amd64 (0.11.2-0.1~deb13u2) ...
 `#9` 24.30 Setting up libxml2:amd64 (2.12.7+dfsg+really2.9.14-2.1+deb13u3) ...
 `#9` 24.30 Setting up libcc1-0:amd64 (14.2.0-19) ...
 `#9` 24.31 Setting up libldap2:amd64 (2.6.10+dfsg-1) ...
 `#9` 24.31 Setting up libzvbi-common (0.2.44-1) ...
 `#9` 24.31 Setting up liblsan0:amd64 (14.2.0-19) ...
 `#9` 24.31 Setting up libmp3lame0:amd64 (3.100-6+b3) ...
 `#9` 24.32 Setting up libitm1:amd64 (14.2.0-19) ...
 `#9` 24.32 Setting up libvorbisenc2:amd64 (1.3.7-3) ...
 `#9` 24.33 Setting up libdvdnav4:amd64 (6.1.1-3+b1) ...
 `#9` 24.33 Setting up libiec61883-0:amd64 (1.2.0-7) ...
 `#9` 24.34 Setting up libserd-0-0:amd64 (0.32.4-1) ...
 `#9` 24.34 Setting up libxkbcommon0:amd64 (1.7.0-2) ...
 `#9` 24.34 Setting up libwayland-client0:amd64 (1.23.1-3) ...
 `#9` 24.34 Setting up libctf0:amd64 (2.44-3) ...
 `#9` 24.35 Setting up libksba8:amd64 (1.6.7-2+b1) ...
 `#9` 24.35 Setting up pinentry-curses (1.3.1-2) ...
 `#9` 24.36 Setting up libavc1394-0:amd64 (0.5.4-5+b2) ...
 `#9` 24.36 Setting up libxcb-dri3-0:amd64 (1.17.0-2+b1) ...
 `#9` 24.36 Setting up libllvm19:amd64 (1:19.1.7-3+b1) ...
 `#9` 24.36 Setting up libx11-xcb1:amd64 (2:1.8.12-1) ...
 `#9` 24.37 Setting up liblapack3:amd64 (3.12.1-6) ...
 `#9` 24.37 update-alternatives: using /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3 to provide /usr/lib/x86_64-linux-gnu/liblapack.so.3 (liblapack.so.3-x86_64-linux-gnu) in auto mode
 `#9` 24.37 Setting up gpg-agent (2.4.7-21+deb13u1+b4) ...
 `#9` 24.80 Setting up libcaca0:amd64 (0.99.beta20-5+deb13u1) ...
 `#9` 24.81 Setting up libzvbi0t64:amd64 (0.2.44-1) ...
 `#9` 24.81 Setting up libxrender1:amd64 (1:0.9.12-1) ...
 `#9` 24.81 Setting up lib...
🧰 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/api/v1/router.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/api/v1/router.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/api/v1/router.py
**/*.{py,js,ts,tsx}

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

Maintain >80% code coverage for new features

Files:

  • src/youtube_extension/backend/api/v1/router.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/api/v1/router.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/api/v1/router.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/api/v1/router.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/api/v1/router.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/api/v1/router.py
🔇 Additional comments (1)
src/youtube_extension/backend/api/v1/router.py (1)

114-121: LGTM!

Also applies to: 687-687, 756-756, 792-792, 1036-1036, 1084-1084

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

Hardens v1 API logging against CWE-117 log injection.

Changes:

  • Adds a CR/LF log sanitizer.
  • Sanitizes identifiers and video URLs in router logs.
  • Adds security regression assertions.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/youtube_extension/backend/api/v1/router.py Sanitizes selected logged values.
tests/unit/test_v1_router_extended.py Tests the sanitizer.
tests/unit/test_cloud_routes.py Verifies sanitized 500 responses.

Comment thread src/youtube_extension/backend/api/v1/router.py
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 17, 2026

@vercel vercel 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.

Additional Suggestion:

_persist_video_job logs a user-controlled job.job_id without CRLF sanitization, allowing log injection (CWE-117)

Fix on Vercel

Copy link
Copy Markdown
Owner Author

Returned to draft because the CWE-117 scope remains live but this exact head is stale and unmergeable.

  • Exact head 32fb0ff484679f7098f42f970ddd83f072f03e3b is 198 commits behind.
  • Current main still logs user-controlled identifiers/URLs directly.
  • Review threads are resolved, but Security and truth-gate evidence are not green on a current head.

Next action: refresh this same canonical branch onto current main, reverify the live log sites and tests, then obtain complete exact-head checks. Do not open a competing implementation.

@groupthinking
groupthinking marked this pull request as draft July 21, 2026 08:07
@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown

Agent Completion Truth Gate: BLOCKED

Reasons: evidence_collection_failed, scope_drift, missing_agent_result, missing_copilot_current_head_review, draft_pr

Machine-readable verdict
{
  "details": {
    "collection_errors": [
      "missing_intent_snapshot"
    ],
    "identity_projection": {
      "agent_login": "claude",
      "issue_number": 913,
      "run_id": "session_01FZcDgrGTkknC2ya13Uy6bU"
    },
    "undeclared_files": [
      "src/youtube_extension/backend/config/logging_config.py",
      "src/youtube_extension/backend/services/video_processing_service.py",
      "src/youtube_extension/utils/logsafe.py",
      "tests/unit/test_logging_config_crlf.py"
    ]
  },
  "reasons": [
    "evidence_collection_failed",
    "scope_drift",
    "missing_agent_result",
    "missing_copilot_current_head_review",
    "draft_pr"
  ],
  "verdict": "blocked"
}

Workflow evidence

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

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

Suppressed comments (2)

tests/unit/test_logging_config_crlf.py:58

  • This test is labeled as covering structured extra fields, but the dictionary is passed as %-formatting arguments, not via extra=, so it only exercises message sanitization. A regression that sanitizes record.getMessage() while leaving formatter-referenced extras unsafe would still pass. Render %(video_url)s from a real extra field and assert the payload remains present on the single sanitized line.
        logger.info(
            "processing %(video_url)s",
            {"video_url": "http://x\r\nADMIN forged-from-extra"},
        )

src/youtube_extension/backend/config/logging_config.py:17

  • The PR description and verification receipt are stale relative to this change: the declared scope lists only the router and its extended test, while the current head (eec7712…) changes six files including this formatter. GitHub currently reports that head as non-draft and dirty, with the truth gate failing and the advertised CI/security runs belonging to the older d0d4b98… head. Update the scope/receipt, return the PR to its required draft state, resolve the base conflict, and rerun exact-head verification before treating these security changes as verified.
from youtube_extension.utils.logsafe import _UNSAFE_LOG_CHARS

Resolves the merge conflict blocking PR #810 by merging the current
`main` into the branch (non-destructive; no force-push).

Two conflicts, both resolved preserving intent from both sides:

- api/v1/router.py imports: dropped the `JSONResponse` import that this
  branch added but never used (unused F401; absent on main). No behavior
  change; brings the file's lint baseline in line with main.

- services/video_processing_service.py LangExtract call: kept main's
  subprocess timeout hardening (`asyncio.wait_for(proc.communicate(...),
  timeout=60)` + `TimeoutError` handling) AND re-applied #810's CWE-117
  sanitization by wrapping the subprocess stderr in `_safe_log(...)`
  before it is logged. Both hardening and log-injection defenses survive.

Verified: both files compile; ruff on the merged files matches main's
pre-existing baseline exactly (no new lint errors, one unused import
removed).

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

Copy link
Copy Markdown
Owner Author

CI triage for head 80add3e (automated remediation scan)

The two red Security Scan checks are transient infrastructure failures, not code findings:

  • Security Scan - python and Security Scan - javascript both completed CodeQL analysis successfully — every query was interpreted (including py/log-injection / js/log-injection, CWE-117) and SARIF was exported. They failed only at the SARIF-upload step:

    API rate limit exceeded for installation ... CodeQL job status was configuration error.

  • This is a GitHub-App REST rate-limit on upload, unrelated to this diff. A re-run once the installation quota resets should clear both. No security regression is present in the changed files.

Other checks: lint-python, lint-frontend, build, guards, bandit, trivy, npm-audit, python-safety, dependency-review, PR Governance, gitleaks, Canonical issue and evidence are green; test and Coverage were still running at scan time.

Remaining blocker is not CI code health — it is agent-completion/truth-gate, which needs a valid historical provenance disposition + trusted terminal agent result, plus the final human review noted in the PR's own draft-exit checklist. This scan did not touch or attempt to satisfy that gate. No autonomous merge is taken: the base is protected main and this PR carries no automerge label, so the merge decision remains with a human reviewer.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Merge conflict resolved — CI green; remaining blockers are human-gated / transient infra

Resolved the merge conflict that was blocking this PR by merging current main into the branch (non-destructive, no force-push) → commit 80add3e. mergeable_state moved dirty → mergeable.

Conflicts resolved (intent preserved from both sides):

  • api/v1/router.py imports — dropped the JSONResponse import this branch added but never used (unused F401, absent on main). No behavior change; the file's ruff baseline now matches main exactly.
  • services/video_processing_service.py LangExtract call — kept main's subprocess timeout hardening (asyncio.wait_for(proc.communicate(...), timeout=60) + TimeoutError handling) and re-applied this PR's CWE-117 sanitization by wrapping the subprocess stderr in _safe_log(...) before logging. Both the hardening and the log-injection defense survive.

CI on the merged head (80add3e):

  • CI (lint + tests, incl. test_v1_router_extended.py) — success; the earlier focused_tests_failed/required_checks_failed in the truth-gate were fail-closed artifacts from evaluating before CI finished, and cleared on the truth-gate's re-run.
  • ✅ Vercel Ready · Agent-completion enforcement · PR Governance · Secret Scan · Dependency Review
  • ⚠️ CodeQL / Security Scan (js + python) — failed with API rate limit exceeded for installation / CodeQL job status was configuration error. This is transient GitHub infra, not a code finding; it clears on re-run.

Remaining blocker is human-gated by design. The agent-completion/truth-gate is still blocked on missing_intent_snapshot + missing_agent_result (plus scope_drift over the four files already carried by this branch, and missing_copilot_current_head_review, which self-resolves once Copilot re-reviews 80add3e). Per this PR's own description — "keep draft and do not weaken or impersonate the gate" — I have not attempted to satisfy or bypass the provenance gate. It needs the trusted intent/agent-result provisioning and a final human review before merge; and main is protected, so the merge itself is a human decision.


Generated by Claude Code

groupthinking pushed a commit that referenced this pull request Aug 2, 2026
StructuredFormatter returned the base-formatted string verbatim, so any
CR/LF carried by user-controlled data or by raw exception text appended
via exc_info / logger.exception could forge or split log lines. Inline
message sanitization (e.g. the _safe_log work on PR #810's router) does
not reach the exc_info traceback or structured `extra` fields, leaving a
log-injection vector on the fully rendered record.

Escape CR/LF and other line separators in the single central sink -
StructuredFormatter.format() - so every logger call (message, extra, and
exc_info traceback) is covered at once, even when a call site forgets to
sanitize its inputs. Escaping (not dropping) keeps the original content
visible and greppable while preventing it from starting a new line.

Complements #810 (#913, #898): that PR hardens message interpolation in
the v1 router; this closes the formatter-level gap Copilot flagged there,
which lives outside #810's router.py scope.

Adds tests/unit/test_logging_config_crlf.py asserting rendered handler
output (not a helper's return value) across the message, exc_info,
logger.exception+extra, and full control-char vectors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BQcuj14cL5gGjdy2Rb925v
groupthinking pushed a commit that referenced this pull request Aug 2, 2026
Scrub CR/LF and other line separators (VT, FF, NEL, U+2028, U+2029) from the
fully rendered log record in StructuredFormatter.format(). Because the scrub
runs on the final formatted string, it covers the message, exc_info traceback
text (including str(exc)), and structured `extra` fields at once — closing the
log-forging vector that inline message sanitizers miss at exc_info /
logger.exception sinks.

Separators are escaped rather than dropped, so content stays greppable while
one logging call is guaranteed to render as one physical line.

Adds tests/unit/test_logging_config_crlf.py asserting the *rendered* handler
output (not a sanitizer return value) cannot be used to forge a standalone log
line via message, exc_info traceback, or Unicode line separators.

Addresses the confirmed unmitigated finding on #810 (CWE-117); this is the
central formatter-level remediation that complements #810's per-sink message
sanitization. Progresses #898.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KDtvQR6b5JXkAStGbTCTxL
groupthinking pushed a commit that referenced this pull request Aug 2, 2026
Entry scan + gate pass under the PR Remediation & Publish Runbook.

30 open PRs: 29 draft (DEFERRED per SCOPE GATE), 1 non-draft (#810).
#810 is HALTED(awaiting human): the agent-completion/truth-gate check
fails by design (provenance gate the PR body says must not be weakened
or impersonated) and awaits final human review; its JS/Python Security
Scan reds are not attributable to its Python-only diff. All required
build/test/lint checks are green.

No PR is autonomously mergeable: protected main + no automerge label
(PUBLISH GATE), drafts (SCOPE GATE), and write scope limited to this
branch. Backlog is stuck at the human/provenance gate, not automation
capacity.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UVDiu5R5LSL2BHL38ZxxYx
@groupthinking
groupthinking marked this pull request as draft August 3, 2026 13:17

Copy link
Copy Markdown
Owner Author

Daily-control containment: returned this PR to draft at its exact current head. The linked issue #913 is stale relative to the current main line; current-head receipt, review, and deployment evidence have not been reconciled. No code or branch was discarded.

Copy link
Copy Markdown
Owner Author

Re-checked on ready-for-review: this PR now conflicts with main and looks superseded

Since my Aug‑2 conflict fix, main has advanced 126 commits (b6bbfb2c23009b), and head 80add3e now conflicts again — in exactly the log-sanitization files:

  • src/youtube_extension/backend/config/logging_config.py
  • tests/unit/test_logging_config_crlf.py
  • tests/unit/test_v1_router_extended.py

The conflict is semantic, not mechanical: main has independently evolved a more complete CWE‑117 defense and taken a different architecture than this PR.

What landed on main (supersedes #913's goal):

main now sanitizes at the formatter levelsanitize_log_record() + _UNSAFE_LOG_CHARS neutralize CR/LF, NUL, and NEL/LS/PS in the final rendered record, plus a json.dumps path — so it protects even values never wrapped at the call site. Consistent with that, main's router.py has zero _safe_log calls and there is no utils/logsafe.py on main: the per-call-site _safe_log wrapping and logsafe util this PR introduces is the approach main deliberately did not take.

Why I did not auto-resolve: picking main's side makes this PR a no-op; picking this PR's side reintroduces an abandoned call-site pattern and would weaken main's formatter-level guarantee. Either way it's a security-architecture decision, not a merge I should make unattended.

Recommendation: close #810 as superseded by the #1270 / #1422 / #1439 CWE‑117 series (its Closes #913 objective is already satisfied on main), unless you want to keep only some specific residual defense-in-depth — in which case that's worth re-scoping as a fresh, small PR against current main. The pre-existing agent-completion/truth-gate provenance blocker and the protected-branch merge decision remain yours regardless.


Generated by Claude Code

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.

Execution: sanitize v1 router log inputs (CWE-117) (PR #810)

3 participants