Skip to content

fix(security): bump brace-expansion + postcss to clear two high CVEs - #725

Closed
seonghobae wants to merge 4 commits into
developfrom
claude/cwlab-pr-audit-governance-1hdcp5
Closed

fix(security): bump brace-expansion + postcss to clear two high CVEs#725
seonghobae wants to merge 4 commits into
developfrom
claude/cwlab-pr-audit-governance-1hdcp5

Conversation

@seonghobae

@seonghobae seonghobae commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Pull Request

Summary

  • npm audit flags two high-severity transitive dev/build advisories in the committed lockfile:
    • brace-expansion ≤5.0.7 — ReDoS via exponential-time expansion of consecutive non-expanding {} groups (GHSA-3jxr-9vmj-r5cp) and unbounded-length OOM crash (GHSA-mh99-v99m-4gvg) — pulled via minimatch/glob.
    • postcss ≤8.5.17 — path traversal in previous source-map auto-loading (GHSA-r28c-9q8g-f849) — pulled via vite.
  • Resolved with npm audit fix (lock-only, 3 packages, semver-compatible per-line bumps). Chosen over a single overrides pin because brace-expansion spans multiple major lines (1.x/2.x/5.x) that must each move to their own patched release. No package.json / source change.

Verification

  • ./scripts/harness/quickcheck.shnot run in full (the Python/Rust lanes are unaffected by an npm lockfile bump). Ran the npm-affected subset instead:
    • npm audit --audit-level=highfound 0 vulnerabilities
    • npm ci → clean (lockfile valid + in sync with package.json)
    • npm run build --workspace @bandscope/desktop → ok (pre-existing chunk-size notice only)
    • npm run test --workspace @bandscope/desktop100% coverage (469/469 stmts, 357/357 branches, 105/105 funcs)

Security Notes

Attack surface

  • Build/dev toolchain only (brace-expansion via glob/minimatch, postcss via vite). Not shipped in the Tauri runtime image or the Python analysis engine.

Trust boundary

  • No trust boundary changes. The advisories are DoS (ReDoS/OOM) and a source-map path traversal in local build tooling; no request/IPC/subprocess path is altered.

Mitigations

  • Move each vulnerable transitive to its patched release so the advisory is removed rather than suppressed (no .trivyignore/audit-suppression added).

Test points

  • npm audit (0 high), npm ci (lock sync), desktop vitest (100% coverage), desktop vite build.

Dependency and Supply Chain

  • No new direct dependency was added
  • If a new dependency was added, this PR explains why it is needed
  • runtime / dev / build / test classification is recorded — both are dev/build transitives
  • alternatives were considered — single overrides pin rejected (brace-expansion multi-major-line)
  • maintainer trust and update health were checked — patch releases of the same packages
  • license fit was checked — unchanged (MIT)
  • known security issues were checked — this PR clears the two flagged advisories
  • transitive footprint impact was considered — 3 lockfile entries changed, no new packages
  • SBOM or supplemental inventory impact was recorded — patch bumps of existing entries only

i18n impact

  • No user-visible string changed
  • Korean and English locale impact was updated — n/a

Reviewer checklist

  • Gitflow target branch is correct — targets develop
  • protected-branch rules were not weakened
  • required checks are expected to stay green

🤖 Generated with Claude Code

https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH


Generated by Claude Code

Summary by CodeRabbit

  • 버그 수정

    • 로컬 오디오 분석 요청에서 localSource가 올바른 객체 형식인지 확인하도록 개선했습니다.
    • 잘못된 형식의 요청은 예외 대신 invalid_request 오류로 안전하게 처리됩니다.
  • 테스트

    • localSource에 객체가 아닌 값이 전달되는 경우의 오류 처리 검증을 추가했습니다.

npm audit flags two high-severity transitive dev advisories in the committed
lockfile:
- brace-expansion <=5.0.7 — ReDoS via exponential-time expansion of consecutive
  non-expanding {} groups (GHSA-3jxr-9vmj-r5cp) and unbounded-length OOM crash
  (GHSA-mh99-v99m-4gvg)
- postcss <=8.5.17 — path traversal in previous source-map auto-loading
  (GHSA-r28c-9q8g-f849)

Resolve via
up to date, audited 391 packages in 963ms

109 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities (lock-only, semver-compatible per-line bumps — 3
packages changed), rather than a single override, because brace-expansion spans
multiple major lines (1.x/2.x/5.x) via minimatch/glob and each must move to its
own patched release. No package.json / source change.

Verified: npm audit --audit-level=high -> 0 vulnerabilities; npm ci -> clean
(lock in sync); npm run build --workspace @bandscope/desktop -> ok; npm run test
--workspace @bandscope/desktop -> 100% coverage (469/469 stmts, 357/357 branches).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 375d8c95-68c7-45f6-9396-6b56d2c930c0

📥 Commits

Reviewing files that changed from the base of the PR and between 39a7f25 and a3fa6ef.

📒 Files selected for processing (1)
  • services/analysis-engine/tests/test_cli.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • services/analysis-engine/tests/test_cli.py

📝 Walkthrough

Walkthrough

로컬 오디오 분석 요청에서 localSource가 사전 타입인지 확인하도록 조건을 강화하고, 문자열 입력이 invalid_request 응답으로 처리되는 테스트를 추가했습니다.

Changes

로컬 오디오 요청 검증

Layer / File(s) Summary
localSource 타입 검증 및 회귀 테스트
services/analysis-engine/src/bandscope_analysis/cli.py, services/analysis-engine/tests/test_cli.py
localSource가 사전인 경우에만 분석을 실행하며, 문자열 입력에는 invalid_request 코드와 필드 오류 메시지를 반환하는 동작을 검증합니다.

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

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 brace-expansion과 postcss 업데이트를 통한 고위험 CVE 해결이라는 PR의 주요 변경 사항을 명확하게 요약합니다.
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 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/cwlab-pr-audit-governance-1hdcp5

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

…ysis engine

The org trivy-fs scan flags two advisories in services/analysis-engine/uv.lock
(pre-existing on develop, surfaced on every PR):
- CVE-2026-55404 (HIGH) yt-dlp 2026.6.9
- CVE-2026-59890 (MEDIUM) setuptools 81.0.0

Remediate the HIGH cleanly: yt-dlp is a direct dep (>=2026.6.9), so
`uv lock --upgrade-package yt-dlp` moves it to 2026.7.4 with no other change
(torch/setuptools untouched; only the yt-dlp lock entry changes).

The setuptools MEDIUM is intentionally NOT fixed here: setuptools>=82 is coupled
to torch (torch 2.12.1 build-requires setuptools<82), so clearing it forces
torch 2.12.1 -> 2.13.0 — a behavior-sensitive ML-runtime bump for demucs stem
separation that cannot be verified in this environment. Flagged on the PR for a
maintainer-verified torch upgrade rather than an unverified push.

Verified: uv lock --upgrade-package yt-dlp -> yt-dlp 2026.7.4, lock consistent
(uv lock --check resolves), diff is the single yt-dlp entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH

Copy link
Copy Markdown
Collaborator Author

The trivy-fs gate flagged two pre-existing base-branch advisories in services/analysis-engine/uv.lock (present on develop, surfaced on every PR), which this PR now partly remediates.

Fixed here (c67a857) — the HIGH, cleanly:

  • CVE-2026-55404 (HIGH), yt-dlpuv lock --upgrade-package yt-dlp moves 2026.6.9 → 2026.7.4. yt-dlp is a direct dep (>=2026.6.9); the diff is the single yt-dlp lock entry, nothing else moved.

Deliberately NOT fixed here — the MEDIUM, because its only fix is coupled to a behavior-sensitive torch bump:

  • CVE-2026-59890 (MEDIUM), setuptools 81.0.0. setuptools is an unconstrained transitive — but --upgrade-package setuptools won't move it, because torch 2.12.1 build-requires setuptools<82. Forcing setuptools>=82 re-resolves torch 2.12.1 → 2.13.0 (+ cuda-toolkit 13.0.2 → 13.0.3.0). That is a minor ML-runtime bump that can change demucs stem-separation output — a quality-sensitive path this engine exists to get right — and it cannot be verified in this environment (no Python 3.12 + the heavy torch/demucs deps to run quickcheck's pytest and a separation regression).

Pushing an unverified torch upgrade would violate "verify before claiming done," so I'm flagging it rather than forcing it. Recommended handling (maintainer decision, since it is behavior-sensitive):

  1. Verified torch upgrade — bump torch to 2.13.0 (which pulls setuptools ≥82), run the full py3.12 quickcheck + a demucs separation regression, and confirm no output drift; or
  2. A narrow, dated .trivyignore entry for CVE-2026-59890 scoped to services/analysis-engine/uv.lock, documenting the torch coupling and a revisit date, if the maintainer judges the build-time setuptools risk acceptable versus a torch bump.

I did not add an ignore autonomously (org policy is remediate-not-suppress), and I did not push the torch bump (unverifiable). Happy to do (1) end-to-end if a Python 3.12 + torch/demucs runner is available.


Generated by Claude Code

The stdin job-request handler's temporary temporal-injection block guarded
localSource with a membership check (`"localSource" in request`) but not a type
check, then called `.get()` on it. A payload with a non-dict localSource (a
string, null, number, or list) — which passes the jobId guard — reached
`local_source.get("sourcePath")` and raised AttributeError. That call sits
outside the block's try/except, so it propagated out of main(), killing the
process with a traceback and writing no JSON envelope — violating cli.main()'s
contract that malformed stdin payloads return a typed `failed`/`invalid_request`
envelope (every other malformed-input path already does).

Fix: guard with `isinstance(request.get("localSource"), dict)` so a non-dict
localSource skips the injection block and falls through to
validate_analysis_job_request (api.py), which raises the contracted
"invalid field 'localSource'" ValueError that run_analysis_job converts to the
invalid_request failure envelope.

Regression test added (test_cli_main_handles_non_dict_local_source); confirmed it
fails with the AttributeError on the pre-fix code and passes after. Python engine
gate green: 658 passed, 100% branch coverage (0 missed), ruff clean, mypy
--strict clean. No i18n impact (no new user-visible string).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH

Copy link
Copy Markdown
Collaborator Author

Added a code-defect fix to this branch (39a7f25), orthogonal to the CVE bumps above.

Defect: cli.py's stdin handler guarded the temporary temporal-injection block with a membership check ("localSource" in request) but no type check, then called .get() on the value. A job payload whose localSource is a non-dict (string / null / number / list) — which passes the jobId guard — reached local_source.get("sourcePath") at cli.py:86 and raised AttributeError. That call is outside the block's try/except, so it propagated out of main(), killing the process with a traceback and writing no JSON envelope — violating main()'s contract that malformed stdin payloads return a typed failed/invalid_request envelope (every other malformed-input path already does). The engine's own validator (api.py validate_analysis_job_request) already treats a non-dict localSource as invalid field 'localSource', but the injection block ran before that validation and bypassed it.

Fix: guard with isinstance(request.get("localSource"), dict) so a malformed localSource skips the injection block and falls through to the real validator, producing the contracted invalid_request failure envelope.

Verification (Python engine gate): added test_cli_main_handles_non_dict_local_source — confirmed it fails with the predicted AttributeError: 'str' object has no attribute 'get' on the pre-fix code and passes after. Full suite: 658 passed, 100% branch coverage (0 missed), ruff clean, mypy --strict clean. No i18n impact (the error text comes from the existing validator; no new user-visible string).


Generated by Claude Code

The prior commit's added assertion tripped `ruff format --check` (the ci /
build-and-test and release-preflight lanes run it), collapsing the message
comparison onto one line. Formatting-only; no behavior change.

Verified: ruff format --check (87 files, exit 0), ruff check clean,
test_cli.py 18 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HdCssGnNMhKHNu3TXFstWH
@seonghobae

Copy link
Copy Markdown
Collaborator Author

Closing as closed-duplicate/superseded (security/CVE cluster) by autonomous product-completion loop.

Winner / disposition target: #727

Unique value from this cluster is consolidated there (projectId path guard + npm HIGH CVE pins + Foote novelty kernel sign). Remaining micro-duplicates do not land additional commercial readiness.

@seonghobae

Copy link
Copy Markdown
Collaborator Author

closed-closed-duplicate/superseded (security/CVE cluster) → #727

@seonghobae seonghobae closed this Jul 31, 2026
auto-merge was automatically disabled July 31, 2026 12:51

Pull request was closed

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.

2 participants