Skip to content

ReactPlugin: malformed bundles may inherit previous plugin components #56169

Closed

Description

@DanInProgress

Apache Airflow version

3.1.0

If "Other Airflow 2 version" selected, which one?

No response

What happened?

Hi! I was reviewing the experimental react_app loading functionality while poking at the new release with some colleagues, and I might? have spotted a minor issue.

Looking at the plugin loading pattern, it appears that plugin authors are asked to assign their exports to globalThis.AirflowPlugin. Could an incorrectly bundled or empty plugin bundle inadvertently reuse the export of a prior plugin bundle?

Note: I haven't had time to create a minimal reproduction yet, and I'm still getting familiar with the code/bundling patterns used, so this might be completely off-base.

What you think should happen instead?

Maybe we could set globalThis.AirflowPlugin to undefined somewhere pre-import or post-assignment? (Minimial changeset, avoid this issue, identical plugin api)

I know this is literally brand new, and still experimental, so my focus is on confusion during prototyping/debugging and not on isolation between plugins. I'm sure there are many changes to come.

How to reproduce

Planned reproduction steps:

  1. Create a minimal PluginA with proper UMD bundle that exports to globalThis.AirflowPlugin
  2. Create a minimal PluginB with malformed/empty UMD bundle that does not set globalThis.AirflowPlugin
  3. Attempt to load PluginA and then PluginB
  4. Check the value of window['PluginB']

Operating System

TODO: update post-reproduction

Versions of Apache Airflow Providers

No response

Deployment

Other

Deployment details

TODO: update post-reproduction

Anything else?

Thanks for your time, and sorry if this turns out to be noise! Just wanted to get this written down while it was fresh in my mind so I could come back to it on monday.

Feel free to close or move to discussions if you think it's more appropriate.

Investigation notes

// Line ~40: Import bundle
import(/* @vite-ignore */ reactApp.bundle_url)
  .then(() => {
    // Line ~44: Check if plugin already cached
    let pluginComponent = globalThis[reactApp.name];
    
    // Line ~47: If not cached, grab from shared global
    if (pluginComponent === undefined) {
      pluginComponent = globalThis.AirflowPlugin;  // ← ISSUE: could this be stale?
      globalThis[reactApp.name] = pluginComponent;
    }
    
    // Line ~51: Validate and return
    if (typeof pluginComponent !== "function") {
      throw new TypeError(`Expected function, got ${typeof pluginComponent}`);
    }
    return { default: pluginComponent };
  })

Code references:

Are you willing to submit PR?

  • Yes I am willing to submit a PR!

Code of Conduct

Activity

  1. boring-cyborg commented on Sep 27, 2025

    @boring-cyborg

    Thanks for opening your first issue here! Be sure to follow the issue template! If you are willing to raise PR to address this issue please do so, no need to wait for approval.

  2. added
    area:UIRelated to UI/UX. For Frontend Developers.
    on Sep 27, 2025
  3. self-assigned this
    on Oct 1, 2025
  4. removed
    needs-triagelabel for new issues that we didn't triage yet
    on Oct 1, 2025
  5. bbovenzi commented on Oct 1, 2025

    @bbovenzi
    Contributor

    Good catch. I'll definitely look into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions