Skip to content

[Bug] hs project dev overrides app cards from a different installed app #1621

Description

@luxferre

Description

When an hs project dev session is active for one app, app cards belonging to a second app installed in the same testing portal can also run the first app's local extension code and configuration.

The apps have different app IDs, app names, OAuth configurations, and allowed URLs. The affected card still sends its own deployed app ID and card ID to HubSpot's CRM extensibility proxy, but the request URL comes from the other app's local profile.

Environment

  • @hubspot/cli: 8.9.1
  • platformVersion: 2025.2
  • @hubspot/ui-extensions: 0.15.0
  • testing portal: developer test account
  • browser: Chromium-based

Setup

  • Example Local App is the app targeted by hs project dev.
  • Example Production App is a separate OAuth app attached to a different HubSpot project in another developer account and installed in the same testing portal.
  • The HubSpot project IDs, developer accounts, app IDs, app names, and card names are different.
  • The local profile adds a postfix to card names, so the affected cards do not have matching titles; the app names also differ.
  • The app/card component uid values are the only confirmed matching project metadata.
  • The local files originated from the same source repository, but this is incidental: HubSpot sees two separate projects and the shared source should not itself establish identity.
  • The apps intentionally use different allowed URLs, which made the incorrect routing visible.

Steps to reproduce

  1. Create separate HubSpot projects and OAuth apps in different developer accounts.
  2. Give the apps and cards different names and configurations while reusing the same relevant app/card component uid values.
  3. Install both apps in the same developer test portal.
  4. Add equivalent app cards from both apps to a CRM record view.
  5. Start hs project dev --profile <local-profile> for Example Local App.
  6. Open a CRM record and interact with the card belonging to Example Production App.
  7. Inspect the request to HubSpot's CRM extensibility proxy.

Actual behavior

The card belonging to Example Production App runs the local code/configuration from Example Local App. A sanitized proxy request looks like this:

POST /api/crm-extensibility/execution/internal/v3/proxy?appId=<production-app-id>&portalId=<testing-portal-id>
{
  "requestUri": "https://local-api.example.test/app-card",
  "method": "POST",
  "appId": "<production-app-id>",
  "cardId": "<production-card-id>",
  "cardTitle": "Record view"
}

Because the local URL is not allowed by Example Production App, the proxy rejects the request:

{
  "status": "error",
  "message": "Requested URL has not been added to Allowed URLs. Contact the App Developer.",
  "category": "FORBIDDEN"
}

All equivalent app cards from the second app appeared to use the local implementation while the dev session was connected.

Expected behavior

Only UI extensions belonging to the app ID associated with the active local development session should run locally. Cards from other installed apps should continue using their deployed code and configuration.

Matching conditions not yet isolated

The HubSpot project IDs, developer accounts, app IDs, app names, and card names differ. The only confirmed matching project metadata is the app/card component uid values. I have not yet tested changing those UIDs independently, so I cannot confirm whether the incorrect local-extension match is based on the app UID, the card UID, or both. Reusing the same source repository is not expected to be relevant because it is not platform-visible.

Impact

  • Local development can unexpectedly replace the behavior of cards from another installed OAuth app.
  • Requests can combine one app's identity and permission allowlist with another app's local endpoint/configuration.
  • Testing becomes misleading when production-like and development app installations coexist in one portal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions