Skip to content

fix: patch xml2js CVE, integrate hush gateway into OpenCode review workflow#33

Closed
byapparov wants to merge 10 commits into
masterfrom
fix/xml2js-hush-review-proxy
Closed

fix: patch xml2js CVE, integrate hush gateway into OpenCode review workflow#33
byapparov wants to merge 10 commits into
masterfrom
fix/xml2js-hush-review-proxy

Conversation

@byapparov
Copy link
Copy Markdown
Contributor

Summary

  • xml2js override to ^0.6.2 — fixes prototype pollution vulnerability (Dependabot alert feat: Improve PII redaction (Phone Numbers) #1, transitive dep via blessed-contribmap-canvasxml2js)
  • Hush gateway @0.1.7 integrated into the OpenCode AI review workflow:
    • Installs and starts hush on :4000
    • Copies hush plugin, configures opencode.json to route API calls through the proxy
    • Defense-in-depth: plugin blocks sensitive file reads, proxy redacts PII before it reaches the model
  • Added build step so tests pass if OpenCode runs them
  • Prompt updated to tell OpenCode not to run tests, just read code and post a single review comment
  • 15-minute timeout on the review step

Changed files

  • package.json / package-lock.json — npm override for xml2js ^0.6.2
  • .github/workflows/opencode-review.yml — hush integration, build step, prompt + timeout tweaks

Test plan

  • Verify npm audit no longer flags xml2js prototype pollution
  • Trigger the OpenCode review workflow on a test PR and confirm hush proxy starts on :4000
  • Confirm the review comment is posted without PII leakage
  • Verify the workflow respects the 15-minute timeout

🤖 Generated with Claude Code

AICtrl Bot and others added 6 commits March 2, 2026 14:52
…hush

- Add npm override for xml2js ^0.6.2 (fixes Dependabot alert #1,
  prototype pollution in transitive dep blessed-contrib → map-canvas → xml2js)
- Integrate hush@0.1.7 into the OpenCode AI review workflow:
  install and start the hush gateway on :4000, copy the hush plugin,
  configure opencode.json to route API calls through the proxy.
  Defense-in-depth: plugin blocks sensitive file reads, proxy redacts
  PII from normal file content before it reaches the model.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Running bare `hush` in the repo checkout resolves to the local
package.json bin entry (dist/cli.js) which doesn't exist in CI
since this workflow doesn't build. Use $(npm prefix -g)/bin/hush
to reliably invoke the globally-installed binary.

Also adds a health-check with ::error:: annotation so the job
fails fast with a clear message if the gateway doesn't start.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ns them

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… comment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 2, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 80.21% 292 / 364
🔵 Statements 79.19% 316 / 399
🔵 Functions 75% 42 / 56
🔵 Branches 68.83% 148 / 215
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/index.ts 77.61% 58.02% 66.66% 82.2% 15, 17, 43-48, 84, 93-95, 144, 161-162, 172, 177, 179, 189, 212-217, 225-232, 239, 258
Generated in workflow #101 for commit 37a0e99 by the Vitest Coverage Report Action

AICtrl Bot and others added 4 commits March 2, 2026 17:13
OpenCode's built-in providers ignore options.baseURL from opencode.json
(anomalyco/opencode#5674). Define a custom "hush-zhipu" provider with
npm adapter @ai-sdk/openai-compatible so the baseURL is actually
respected and all LLM traffic routes through the hush gateway.

Verified locally: hush logs show requests at /api/coding/paas/v4/chat/completions
with tokenCount > 0 (PII redaction active).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GLM-5 takes 3-8 minutes per inference, making it impossible to complete
a multi-file code review within the 15-minute timeout. GLM-4.7-flash
responds in seconds and is sufficient for code review quality.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OpenCode wasted 12 minutes trying to discover the PR number via
`gh pr view` (fails in detached HEAD) and `gh pr list --branch`
(flag not available in CI's gh version). Pass $PR_NUMBER directly
in the prompt so it can post the comment immediately.

Also bump the proxy fetch timeout from 30s to 120s — LLM first-token
latency can exceed 30s for large prompts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aictrl-dev aictrl-dev deleted a comment from github-actions Bot Mar 2, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 2, 2026

Code Review: PR #33

✅ Approved

The changes are well-structured and address the xml2js CVE while properly integrating the Hush gateway into the OpenCode review workflow.


1. Redaction Logic (src/middleware/redactor.ts)

Solid. The redactor handles multiple PII types:

  • ✅ Emails, IPs (v4/v6), phone numbers with good regex patterns
  • ✅ Cloud provider keys (AWS, GCP, GitHub, etc.) with specific prefixes
  • ✅ Generic secrets via key-value pattern matching
  • ✅ Sensitive JSON keys (apikey, secret, password, token, etc.)
  • ✅ PEM private keys (multiline-aware)

Minor consideration: The SECRET pattern (/(?:api[-_]?key|secret|...)[...] {16,}/gi) requires 16+ chars. Short secrets (e.g., 8-15 char DB passwords) in config files won't be caught. Acceptable trade-off for false-positive reduction.


2. Streaming Integrity (src/vault/token-vault.ts:87-225)

Well-designed. The createStreamingRehydrator() correctly:

  • ✅ Detects SSE vs raw text mode
  • ✅ Buffers incomplete lines until newline arrives
  • ✅ Holds back potential partial tokens (tokens split across chunks)
  • ✅ Handles both OpenAI/ZhipuAI and Anthropic delta formats
  • ✅ Caps buffer size at 1MB to prevent unbounded memory growth
  • ✅ Smart bracket detection to distinguish token prefixes from JSON arrays

No unnecessary buffering — content is released as soon as it's safe.


3. Security

Good.

  • ✅ Localhost-only binding by default (HUSH_HOST defaults to 127.0.0.1)
  • ✅ Optional HUSH_AUTH_TOKEN for proxy auth with flexible header support
  • ✅ Plugin blocks sensitive file reads (.env, *.pem, credentials.*, etc.)
  • ✅ Token vault has 1-hour TTL with automatic pruning
  • structuredClone for safe deep copies in rehydration
  • ⚠️ Note: DEBUG=true exposes vaultSize on /health — acceptable for debugging but should not be enabled in production

4. Reliability (src/index.ts:100-163)

Solid.

  • ✅ Upstream errors (4xx/5xx) properly forwarded with status codes
  • ✅ Backpressure handling in streaming (res.once('drain'))
  • ✅ Generic 502 on fetch failures
  • ✅ Timeout increased from 30s → 120s (appropriate for LLM cold starts)

Workflow Integration

The workflow correctly:

  • Installs hush globally, starts it on port 4000
  • Waits for health check before proceeding
  • Configures custom provider routing through the proxy
  • Includes 15-minute timeout safeguard

One minor suggestion: Consider logging the error body in the 502 handler at debug level for easier troubleshooting without leaking upstream details.

Reviewed SHA: 37a0e99

@byapparov
Copy link
Copy Markdown
Contributor Author

Superseded by #34 — the suspected OpenCode baseURL bug doesn't exist. The built-in provider override works correctly, so the custom hush-zhipu provider workaround is unnecessary. #34 uses the simpler approach and is already passing CI with a successful hush-proxied review.

@byapparov byapparov closed this Mar 2, 2026
@byapparov byapparov deleted the fix/xml2js-hush-review-proxy branch March 3, 2026 10:25
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