Skip to content

bug(onboarding): External ID regenerates on every modal reopen — silent AssumeRole break #126

@cristim

Description

@cristim

Symptom

When a user clicks Add AWS Account, populateAwsAccountFields(undefined) calls generateExternalID() which auto-fills the External ID input with a fresh UUID X. If the user copies X into their AWS IAM trust policy, then closes the modal without saving (cancel / browser refresh / nav / auth-token expiry), and reopens Add AWS Account later, the input is populated with a different UUID Y. The user saves with Y but their trust policy still has X. STS AssumeRole then fails with AccessDenied: ExternalId mismatch and the operator has no easy way to see the mismatch.

This is a real workflow that produces a silently-broken account configuration with no diagnostic affordance.

Reproduction

  1. Settings → Accounts → Add AWS Account.
  2. Note the auto-generated External ID (call it X). Open the AWS console, paste X into the IAM role's trust-policy sts:ExternalId condition. Save the role.
  3. Close the modal in CUDly without saving.
  4. Reopen Add AWS Account. Observe a different External ID (Y) auto-fills the field.
  5. Fill the rest of the form, save. CUDly stores Y.
  6. CUDly tries to assume the role → AWS rejects with AccessDenied because Y ≠ X.

Expected

One of:

  • Persist a draft external_id in sessionStorage keyed on a draft-account-id, and only regenerate if no draft exists. Clear on successful save.
  • Generate at save-time instead of open-time. Modal shows a placeholder ("auto-generated on save"); after save, the operator returns to a confirmation/instruction view that displays the now-frozen External ID + ready-to-paste trust-policy snippet.
  • Explicit "Regenerate" button beside a stable, modal-lifetime ID — never silent regeneration.
  • Diagnostic UI on AssumeRole failure that surfaces the configured ExternalId so the operator can compare against what's in their trust policy.

The first option is the smallest change: persist on every keystroke / focus-out, regenerate only when missing.

Severity

High. Most likely real-world breakage path for the External ID feature, with no user-facing affordance to detect or recover from it.

Test coverage gap

settings-accounts.test.ts:362 (add-aws-account-btn auto-generates the External ID) only verifies some value is generated — it doesn't lock in the stability across modal reopens behaviour that any of the mitigations above would introduce.

Related

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions