Skip to content

fix(security): honor endpoint overrides only in dev builds - #160

Merged
joshdholtz merged 3 commits into
mainfrom
dx-sec-endpoints-dev-only
Aug 27, 2026
Merged

fix(security): honor endpoint overrides only in dev builds#160
joshdholtz merged 3 commits into
mainfrom
dx-sec-endpoints-dev-only

Conversation

@joshdholtz

@joshdholtz joshdholtz commented Aug 27, 2026

Copy link
Copy Markdown
Member

The API/service endpoints are overridable via env vars, which is only ever useful for local development against staging. In a shipped binary those overrides are just a way for a poisoned env or profile to send a customer's credential somewhere else. This locks release builds to production.

  • RC_BASE_URL + profile base_url, RC_PAYWALL_AI_BASE_URL, RC_RICO_BASE_URL are honored only in local dev builds.
  • Release binaries always use the production endpoints, regardless of those vars.
  • New internal/buildinfo carries the dev/release signal from main's version, so there's no goreleaser change.

Dev workflow is unchanged: a local go build/go run still honors the overrides.

Not touched: RC_OAUTH_BASE_URL is the same class and could get the same treatment, but it's in the auth flow so I left it out of this pass, ask if you want it in.


Note

High Risk
Changes authentication and API routing for all credential-bearing traffic; incorrect dev/release detection could break staging workflows or fail to block override attacks in release builds.

Overview
Release binaries no longer honor endpoint override env vars or profile base_url, so credentials and API keys cannot be redirected via poisoned environment or config in shipped builds.

A new internal/buildinfo package exposes IsDev() (version "dev" for local go build/go run; release versions from ldflags). main sets buildinfo.Version at startup. devEnvOrDefault and Runtime.effectiveBaseURL() apply overrides only when IsDev() is true.

Affected paths: API client base URL (RC_BASE_URL / profile), SDK calls (offerings, simulated purchase), Paywalls AI (RC_PAYWALL_AI_BASE_URL), Rico (RC_RICO_BASE_URL), and OAuth refresh host (RC_OAUTH_BASE_URL). envOrDefault moves to env.go; tests cover IsDev and devEnvOrDefault.

Local dev behavior is unchanged when the binary is built with version dev.

Reviewed by Cursor Bugbot for commit d736bbd. Bugbot is set up for automated code reviews on this repo. Configure here.

RC_BASE_URL (and profile base_url), RC_PAYWALL_AI_BASE_URL, and RC_RICO_BASE_URL
are now honored only in local dev builds. A shipped (release) binary always talks
to the production RevenueCat endpoints, so a poisoned env or profile can't redirect
a customer's credential elsewhere. New internal/buildinfo carries the dev/release
signal from main's version.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@joshdholtz
joshdholtz requested review from alfondotnet and a lite review from Copilot August 27, 2026 00:06
@joshdholtz

Copy link
Copy Markdown
Member Author

bugbot run

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread internal/cli/runtime.go
customers simulate-purchase and offerings preview build an SDK service with
rt.Config.BaseURL directly, bypassing the API() gate. Route them through a new
Runtime.effectiveBaseURL() so a release binary never sends the public SDK key to
a base_url override either.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@joshdholtz

Copy link
Copy Markdown
Member Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

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

Reviewed by Cursor Bugbot for commit 793103f. Configure here.

@fire-at-will fire-at-will left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think there's one missed URL that needs protecting, otherwise looks good!

Slightly related, but can go in a different PR: do we maybe want to remove the --base-url flags in release builds for the same reason?


import (
"testing"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change

Nit: no need for this newline

Comment thread internal/cli/rico.go Outdated
return fallback
}

// devEnvOrDefault honors an endpoint override env var only in dev builds; a

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is rico.go the best place for this function to live? It's a utility that is shared across many features and isn't rico-specific

Comment thread internal/cli/runtime.go Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think we should protect this call as well, otherwise oath credentials could be redirected here

Per review: also lock the OAuth base URL to production in release builds so
auth can't be redirected, and move envOrDefault/devEnvOrDefault to env.go since
they're shared, not rico-specific.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@joshdholtz
joshdholtz merged commit 5d81976 into main Aug 27, 2026
5 checks passed
@joshdholtz
joshdholtz deleted the dx-sec-endpoints-dev-only branch August 27, 2026 13:35
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.

3 participants