fix(security): neutralize CR/LF in rendered log records (CWE-117) - #1265
fix(security): neutralize CR/LF in rendered log records (CWE-117)#1265groupthinking wants to merge 2 commits into
Conversation
invalidate_by_tags() issued smembers+delete one tag at a time, so the caller's wall-clock latency grew linearly with tag count and stale entries stayed readable for the whole window. Fan the per-tag work out with asyncio.gather, reusing the per-layer tag-write semaphore already introduced for set() so the combined fan-out cannot exhaust the shared connection pool. One permit covers both commands for a tag since the delete depends on the smembers result. Closes #1261. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
StructuredFormatter previously returned the fully rendered record verbatim, so any newline/carriage-return in the record body could forge additional log lines. Inline call-site sanitizers cannot cover every sink: exc_info tracebacks (str(exc) + frames) and structured `extra` fields are appended by the formatter itself, after any per-argument sanitization runs. Neutralize line/escape separators (CR, LF, VT, FF, ESC, NEL, U+2028, U+2029) in the final rendered string inside StructuredFormatter.format(), so message, traceback, and extras are all covered at a single choke point regardless of the call site. Separators are escaped (not dropped), keeping multi-line tracebacks fully diagnosable on one physical line with no information loss. Adds tests/unit/test_logging_config_crlf.py asserting against rendered handler output for the message, exc_info-traceback, structured-extra, and Unicode-separator vectors, plus a parametrized check that every declared unsafe character is neutralized. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RirdQCKDByp2a8qdLb8PXh
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 59 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (2)
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. Comment |
Agent Completion Truth Gate: BLOCKEDReasons: Machine-readable verdict{
"details": {
"invalid_fields": [
"issue.number",
"policy.agent_login",
"policy.run_id"
]
},
"reasons": [
"invalid_payload"
],
"verdict": "blocked"
} |
|
@coderabbitai full review Generated by Claude Code |
|
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 59 minutes. |
Status — draft, code-green, halted on human/owner gatesConsolidated disposition for this PR (supersedes the individual check-failure notifications, which are duplicate re-runs of the classes below). What this PR does: closes a confirmed CWE-117 log-forging vector in Code checks: green — Red checks — none are code defects:
Terminal state: HALTED — awaiting (1) owner provenance pass on the truth-gate and (2) human merge approval to protected Note: this branch also carries one pre-existing, owner-authored commit — Generated by Claude Code |
|
Closing as strictly dominated and conflicting. On the formatter, this PR neutralizes Its one unique contribution — the Full comparison matrix and consolidation plan: #1270 (comment). Reopen if the |
Canonical issue
Progresses the router-wide CWE-117 hardening tracked by #810 / #913 / #898 by closing the residual sink those PRs could not reach from
router.pyalone. No single issue is claimed asCloses— this is the central-formatter half of that work.Outcome
StructuredFormattercan no longer emit forged or corrupted log lines from attacker-controlled text. Inline call-site sanitizers (e.g._safe_login the v1 router) only scrub the interpolated message; the formatter itself appendsexc_infotracebacks (str(exc)+ frames) and structuredextrafields after any per-argument sanitization runs. AValueError("boom\r\nCRITICAL - ...")surfaced vialogger.error(..., exc_info=True)therefore still forged a physical log line. This closes that vector at a single choke point, independent of whether any given call site sanitized its inputs.Scope
src/youtube_extension/backend/config/logging_config.py— neutralize line/escape separators in the fully rendered record insideStructuredFormatter.format().tests/unit/test_logging_config_crlf.py— new regression tests asserting against rendered handler output.router.py_safe_logcall sites (owned by fix(security): sanitize user-controlled values in API logs (CWE-117 log injection) #810; untouched here to avoid scope drift).logging_config.py(kept the diff to the security change only).Risk
Verification
tests/unit/test_logging_config_crlf.py: 11 passed (message CRLF,exc_infotraceback, structuredextra, Unicode separators, and a parametrized check that every declared unsafe char is neutralized).ruff checkclean; new code isblack-compliant.Production evidence
Not applicable to a Vercel preview: this is a Python-only backend logging change; the Next.js
apps/webpreview does not exercise it. Covered by the unit regression suite above.Agent handoff
router.pyscopelogging_config.py)main) — this run does not auto-mergeNote on branch contents
This branch also carries one pre-existing, owner-authored commit —
perf: invalidate Redis tags concurrently instead of serially— that predates this session and was not created here. Its canonical issue linkage lives solely on its dedicated PR #1262, which is the sole implementer of that cache-invalidation issue; this security PR claims no issue of its own. The commit is preserved rather than discarded, and git authorship is intact. Reviewers may drop it here once #1262 lands.Generated by Claude Code