Skip to content

Onsite dev#130

Closed
howethomas wants to merge 7 commits intomainfrom
onsite-dev
Closed

Onsite dev#130
howethomas wants to merge 7 commits intomainfrom
onsite-dev

Conversation

@howethomas
Copy link
Contributor

@howethomas howethomas commented Mar 2, 2026

Note

Medium Risk
Adds new unauthenticated GET /stats/queue endpoint and introduces new link code that performs external HTTP requests and mutates stored vCons, which could impact security/performance if misconfigured. Docker/compose changes are low risk but expand the local deployment footprint.

Overview
Adds an optional SigNoz observability stack (docker-compose.signoz.yml plus ClickHouse/collector configs) to run alongside the existing deployment for OTEL traces/metrics/logs.

Updates the runtime image build to force Debian APT sources to HTTPS, improving compatibility in networks where HTTP (port 80) is blocked.

Extends the API with a public GET /stats/queue endpoint that returns Redis list depth for monitoring/backpressure, and updates the webhook link to normalize outgoing vCon payloads to vcon: "0.3.0".

Introduces two new processing links: wtf_transcribe (posts recording dialogs to a vfun transcription server and stores results as wtf_transcription analysis) and keyword_tagger (scans transcription/WTF analysis text for predefined/custom keywords and adds matching tags).

Written by Cursor Bugbot for commit cefef64. Configure here.

howethomas and others added 7 commits January 27, 2026 22:24
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates webhook link to set vcon version to 0.3.0 for
compatibility with vcon-mcp REST API.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Configure apt to use HTTPS sources for environments
where HTTP port 80 is blocked.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Includes docker-compose and config files for SigNoz
observability stack with OpenTelemetry collector.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Public endpoint (no auth) that returns the depth of any Redis list,
used by the audio adapter for backpressure control.

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

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 5 potential issues.

Bugbot Free Tier Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

return JSONResponse(content={"list_name": list_name, "depth": depth})
except Exception as e:
logger.error(f"Error getting queue depth for '{list_name}': {str(e)}")
raise HTTPException(status_code=500, detail="Failed to get queue depth")
Copy link

Choose a reason for hiding this comment

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

Unauthenticated endpoint allows probing arbitrary Redis keys

High Severity

The /stats/queue endpoint is registered directly on @app.get() (bypassing the api_router auth), and accepts an arbitrary list_name parameter passed directly to redis_async.llen(). This allows unauthenticated users to probe any Redis key to discover queue names, check if specific keys exist, and observe queue depths — enabling reconnaissance of the system's internal state. The list_name parameter has no validation or allowlist restricting it to known queue names.

Fix in Cursor Fix in Web

### Start without SigNoz (normal operation)

```bash
cd /home/thomas/bds/vcon-dev/vcon-server
Copy link

Choose a reason for hiding this comment

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

Hardcoded personal dev paths in shared documentation

Low Severity

The README contains hardcoded absolute paths (/home/thomas/bds/vcon-dev/vcon-server) from a developer's local machine. These are developer-specific and not meaningful for other contributors. Relative paths or a generic placeholder would be appropriate here.

Fix in Cursor Fix in Web

# Other Content
"other": {
"profanity": ["fuck", "shit", "damn", "ass"],
"mentions_torn": ["torn"],
Copy link

Choose a reason for hiding this comment

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

Substring matching causes excessive false positives for profanity

Medium Severity

The find_keywords function uses plain substring matching (if search_keyword in text). The profanity list includes short words like "ass" which will match extremely common words such as "class", "pass", "massage", "assist", "assembly", etc. This will incorrectly tag a large number of vCons with the profanity tag, undermining the reliability of the keyword tagger.

Additional Locations (1)

Fix in Cursor Fix in Web

# Send audio to vfun server
files = {"file": (filename, audio_content, mimetype)}
data = {
"diarize": str(opts.get("diarize", True)),
Copy link

Choose a reason for hiding this comment

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

Diarize parameter sent as "True" instead of "true"

Medium Severity

str(opts.get("diarize", True)) produces "True" (capital T) in Python, but the vfun server expects lowercase "true" — as shown in the README's curl example (-F "diarize=true") and consistent with the adjacent "block": "true" field. If the server does a strict string comparison, diarization would silently fail to activate despite being enabled.

Fix in Cursor Fix in Web

elif encoding == "base64":
return base64.b64decode(dialog["body"])
else:
return dialog["body"].encode() if isinstance(dialog["body"], str) else dialog["body"]
Copy link

Choose a reason for hiding this comment

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

Unhandled base64 decode error crashes entire link processing

Medium Severity

get_audio_content wraps file I/O and HTTP fetches in try/except blocks, returning None on failure, but the base64.b64decode / base64.urlsafe_b64decode calls at lines 80–82 are unprotected. Since the call to get_audio_content at line 261 sits outside the per-dialog try/except block (which starts at line 269), a corrupt or truncated base64 body will raise binascii.Error, crash the run() function, and abort processing of all remaining dialogs in the vCon.

Additional Locations (1)

Fix in Cursor Fix in Web

@howethomas howethomas closed this Mar 4, 2026
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