Skip to content

fix: don't audit the Convox CLI's own requests as denials - #187

Merged
ndbroadbent merged 2 commits into
mainfrom
nathan/quiet-convox-cli-requests
Oct 25, 2026
Merged

ndbroadbent merged 2 commits into
mainfrom
nathan/quiet-convox-cli-requests

Conversation

@ndbroadbent

@ndbroadbent ndbroadbent commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

Since v0.1.15 the gateway audits requests for rack routes it doesn't forward as denials. That turned up requests the Convox CLI makes for itself on every deploy, run and log stream. No rack answers them, and the CLI ignores the 404:

  • GET /machines and GET /racks: the Convox SDK sends one before each websocket (build logs, run, exec, logs) to start a Convox Console session (sdk/sdk.go, Websocket). It discards the answer, and a self-hosted rack has neither route. /racks has been there since 2019; /machines came with Convox's cloud CLI in 3.22.2.
  • GET /apps/{app}/configs/cli-env-mask: convox env and convox releases info read Convox's own env mask (convox env mask set) before printing to a terminal. On a 404 they print the env as it came, and the gateway has already masked secret values in it.

These requests say nothing about the caller, so each one only added a denial row: a few dozen a day per rack for an ordinary deploy pipeline.

Change

  • isRoutineConvoxCLIRequest lists the three requests by exact method and canonical path. The gateway still answers them with 404 and writes the request log line, but records no denial.
  • A request that only resembles one is still a denial: another method (PUT .../cli-env-mask from convox env mask set), another config name, a websocket upgrade, or a path that fails isSafeRackPath.
  • Docs: the audit trail's Denied Requests section, the permissions page, AGENTS.md (where to add such a request after a Convox upgrade) and internal/gateway/AGENTS.md.

Not adapting to Convox's env mask

The gateway already masks env values before they leave it: secret-looking names, CONVOX_SECRET_ENV_VARS, each app's secret_env_vars and protected_env_vars, and values with credentials in them. Convox's mask only hides values when the CLI prints to a terminal, and the rack still returns them in full. Its per-app key list does the same job as secret_env_vars. Answering the read with the gateway's own list would change nothing, since those values already arrive masked. App configs can hold secrets, so /configs stays unforwarded.

Testing

  • TestIsRoutineConvoxCLIRequest covers the three matches and the near misses.
  • TestRoutineConvoxCLIRequestsAreNotAuditedAsDenials: 404, nothing forwarded, no audit entry even after the repeat counts are flushed.
  • TestNearRoutineRequestsAreStillAuditedAsDenials: a PUT of the mask, another config, a machine ID, a websocket upgrade, a dot-segment app and an encoded ? are each recorded as a denial.
  • Mutation checks, each caught by a test: always recording the denial, dropping the safe-path guard, and accepting any method.
  • task go:lint is clean and ./internal/gateway/proxy/ passes.

Summary by CodeRabbit

  • Bug Fixes
    • Routine Convox CLI requests to /machines, /racks, and the CLI environment-mask config endpoint still receive a 404 without being recorded as denied. The environment-mask request remains in the request log. Other methods and similar unmatched requests continue to be audited as denials.
  • Documentation
    • Updated security and audit-trail guidance to clarify which routine CLI requests are excluded from denial entries and how other requests are handled.

Since unforwarded rack routes became denials, every deploy, run and log stream has
added one or two: the Convox CLI makes requests for itself that no rack answers,
and it ignores the 404.

- GET /machines and GET /racks: the SDK sends one before each websocket (build
  logs, run, exec, logs) to start a Convox Console session.
- GET /apps/{app}/configs/cli-env-mask: `convox env` and `convox releases info`
  read Convox's env mask before printing to a terminal, and print the env as it
  came on a 404. The gateway has already masked secret values.

The gateway still answers these with 404 and writes the request log line, but no
denial entry. Another method, another config name, a websocket upgrade, or a path
that isn't a safe rack path is still a denial.
@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 7dfdbf52-19f1-4ce2-8911-cb515935a804
Commits

Reviewing files that changed from the base of the PR and between 1cd02de and 1e2c16e.

Files selected for processing: 2
  • convox.yml
  • web/package.json

Included review availability: This review used your included allowance. 1 included review remains after this review. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.

Walkthrough

The gateway recognizes three routine Convox CLI GET requests and returns 404 for them without recording denial audit entries. Other unmatched or unsafe routes continue to be logged and audited. Documentation describes the request and denial behavior. The gateway and admin image tags and web package version change to 0.1.23.

Changes

Routine CLI Request Auditing

Layer / File(s) Summary
Routine request classification
internal/gateway/proxy/convox_cli_requests.go, internal/gateway/proxy/convox_cli_requests_test.go
A predicate matches GET requests to /machines, /racks, and /apps/{app}/configs/cli-env-mask. Tests check these matches and reject other methods and path shapes.
Route refusal and audit handling
internal/gateway/proxy/handler.go, internal/gateway/proxy/convox_cli_requests_test.go, internal/gateway/AGENTS.md, AGENTS.md, docs/src/content/docs/security/compliance/audit-trail.mdx, docs/src/content/docs/security/rbac/permissions.mdx
For routine requests with unmatched or unsafe routes, the gateway still logs the denial and returns 404 but skips denial recording. Tests cover these requests and near-matches. Guidance and security documentation describe the behavior.
Release version updates
convox.yml, web/package.json
The gateway and admin image tags change to v0.1.23. The web package version changes to 0.1.23.

Priority: Low

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

Change: Bug fix

Merge Risk: Minimal · up to 1e2c1

The three routine CLI requests still return 404 while only their denial audit records are skipped; similar requests remain audited.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: excluding the Convox CLI's routine requests from denial auditing.
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.
Full details: Docstring Coverage

Explanation

Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 3 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit checks the routes at night,
Three CLI paths return 404 right.
No denial entry marks their way,
Other requests are logged as they stray.
The tags now point to versions new,
The rabbit hops along its queue.

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

@deepsource-io

deepsource-io Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in a6d8a66...1e2c16e on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
JavaScript Oct 25, 2026 7:54p.m. Review ↗
Go Oct 25, 2026 7:54p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

@ndbroadbent
ndbroadbent merged commit c5eb811 into main Oct 25, 2026
14 checks passed
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