Who we are

Our Technologies

Our Company

Friday, February 6, 2026

Security Hardening: 8 Fixes Shipped for Oxy Services

Security Hardening: 8 Fixes Shipped for Oxy Services

Security Hardening: 8 Fixes Shipped for Oxy Services

We take security seriously at Oxy. This week we identified and resolved 8 issues across OxyHQ Services, our core backend module that powers authentication, billing, and session management. Here's what we fixed and why it matters.

Critical Fixes

Stripe webhook secret validation at startup (#183): The getWebhookSecret() function could return an empty string at runtime if the environment variable wasn't set. While Stripe's constructEvent would fail per-request, the webhook endpoint was still registered and accepting requests. We now validate the secret at server startup and fail fast if it's missing.

Billing credit amount caps (#182): Our credit checkout stored package credits in Stripe metadata, but the webhook handler that processed completed checkouts wasn't re-validating the credit amount against our known packages. A forged or replayed webhook with modified metadata could theoretically grant unlimited credits. We added server-side re-validation and capped credit amounts in the webhook handler.

FedCM CORS origin whitelist (#181): The FedCM endpoints were reflecting any request origin in CORS headers combined with Access-Control-Allow-Credentials: true. Without an origin whitelist, any domain could potentially obtain ID tokens or user account information. We implemented a strict origin allowlist for all FedCM-related endpoints.

High Severity Fixes

CSRF bypass via X-Native-App header (#184): Any request with the X-Native-App: true header was bypassing CSRF cookie matching entirely. The middleware only checked that the header token existed and met a minimum length. We tightened this by requiring proper token validation regardless of the native app header.

Memory leak in session management (#189): The trackRemovedSession function used setTimeout callbacks that were never cleaned up on component unmount. With frequent session removals, timer callbacks accumulated and held references to stale refs. We added proper cleanup on unmount.

Stale closure in OxyProvider session restoration (#187): The restoreSessionsFromStorage callback captured dependencies that changed when the sessions array changed, causing effects to re-run with stale closures. This created race conditions during session restoration. We restructured the dependency chain to prevent stale captures.

Medium Severity Fixes

IdP session check iframe cleanup (#192): Rapid calls to checkIdPSession could overwrite the cleanup reference without calling the previous cleanup function, leaving orphaned iframes in the DOM. We now always call the previous cleanup before setting a new one.

Session cache invalidation (#196): getUserBySession() cached responses with a 2-minute TTL, but if a session was revoked server-side, the client kept serving stale data. We now invalidate the cache immediately when a session validation fails.

What's Next

We're continuing to audit our authentication and billing infrastructure. All fixes are available now in the latest release of @oxyhq/services. If you're building on top of Oxy Services, update your dependencies to get these patches.

You can track all open issues and contribute fixes on our GitHub repository.

We take security seriously at Oxy. This week we identified and resolved 8 issues across OxyHQ Services, our core backend module that powers authentication, billing, and session management. Here's what we fixed and why it matters.

Critical Fixes

Stripe webhook secret validation at startup (#183): The getWebhookSecret() function could return an empty string at runtime if the environment variable wasn't set. While Stripe's constructEvent would fail per-request, the webhook endpoint was still registered and accepting requests. We now validate the secret at server startup and fail fast if it's missing.

Billing credit amount caps (#182): Our credit checkout stored package credits in Stripe metadata, but the webhook handler that processed completed checkouts wasn't re-validating the credit amount against our known packages. A forged or replayed webhook with modified metadata could theoretically grant unlimited credits. We added server-side re-validation and capped credit amounts in the webhook handler.

FedCM CORS origin whitelist (#181): The FedCM endpoints were reflecting any request origin in CORS headers combined with Access-Control-Allow-Credentials: true. Without an origin whitelist, any domain could potentially obtain ID tokens or user account information. We implemented a strict origin allowlist for all FedCM-related endpoints.

High Severity Fixes

CSRF bypass via X-Native-App header (#184): Any request with the X-Native-App: true header was bypassing CSRF cookie matching entirely. The middleware only checked that the header token existed and met a minimum length. We tightened this by requiring proper token validation regardless of the native app header.

Memory leak in session management (#189): The trackRemovedSession function used setTimeout callbacks that were never cleaned up on component unmount. With frequent session removals, timer callbacks accumulated and held references to stale refs. We added proper cleanup on unmount.

Stale closure in OxyProvider session restoration (#187): The restoreSessionsFromStorage callback captured dependencies that changed when the sessions array changed, causing effects to re-run with stale closures. This created race conditions during session restoration. We restructured the dependency chain to prevent stale captures.

Medium Severity Fixes

IdP session check iframe cleanup (#192): Rapid calls to checkIdPSession could overwrite the cleanup reference without calling the previous cleanup function, leaving orphaned iframes in the DOM. We now always call the previous cleanup before setting a new one.

Session cache invalidation (#196): getUserBySession() cached responses with a 2-minute TTL, but if a session was revoked server-side, the client kept serving stale data. We now invalidate the cache immediately when a session validation fails.

What's Next

We're continuing to audit our authentication and billing infrastructure. All fixes are available now in the latest release of @oxyhq/services. If you're building on top of Oxy Services, update your dependencies to get these patches.

You can track all open issues and contribute fixes on our GitHub repository.

We take security seriously at Oxy. This week we identified and resolved 8 issues across OxyHQ Services, our core backend module that powers authentication, billing, and session management. Here's what we fixed and why it matters.

Critical Fixes

Stripe webhook secret validation at startup (#183): The getWebhookSecret() function could return an empty string at runtime if the environment variable wasn't set. While Stripe's constructEvent would fail per-request, the webhook endpoint was still registered and accepting requests. We now validate the secret at server startup and fail fast if it's missing.

Billing credit amount caps (#182): Our credit checkout stored package credits in Stripe metadata, but the webhook handler that processed completed checkouts wasn't re-validating the credit amount against our known packages. A forged or replayed webhook with modified metadata could theoretically grant unlimited credits. We added server-side re-validation and capped credit amounts in the webhook handler.

FedCM CORS origin whitelist (#181): The FedCM endpoints were reflecting any request origin in CORS headers combined with Access-Control-Allow-Credentials: true. Without an origin whitelist, any domain could potentially obtain ID tokens or user account information. We implemented a strict origin allowlist for all FedCM-related endpoints.

High Severity Fixes

CSRF bypass via X-Native-App header (#184): Any request with the X-Native-App: true header was bypassing CSRF cookie matching entirely. The middleware only checked that the header token existed and met a minimum length. We tightened this by requiring proper token validation regardless of the native app header.

Memory leak in session management (#189): The trackRemovedSession function used setTimeout callbacks that were never cleaned up on component unmount. With frequent session removals, timer callbacks accumulated and held references to stale refs. We added proper cleanup on unmount.

Stale closure in OxyProvider session restoration (#187): The restoreSessionsFromStorage callback captured dependencies that changed when the sessions array changed, causing effects to re-run with stale closures. This created race conditions during session restoration. We restructured the dependency chain to prevent stale captures.

Medium Severity Fixes

IdP session check iframe cleanup (#192): Rapid calls to checkIdPSession could overwrite the cleanup reference without calling the previous cleanup function, leaving orphaned iframes in the DOM. We now always call the previous cleanup before setting a new one.

Session cache invalidation (#196): getUserBySession() cached responses with a 2-minute TTL, but if a session was revoked server-side, the client kept serving stale data. We now invalidate the cache immediately when a session validation fails.

What's Next

We're continuing to audit our authentication and billing infrastructure. All fixes are available now in the latest release of @oxyhq/services. If you're building on top of Oxy Services, update your dependencies to get these patches.

You can track all open issues and contribute fixes on our GitHub repository.

Latest news

Latest news

Latest news