[$250] Security - No warning message when "Full coplilot" removes "Limit copilot"
If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!
Version Number: v9.2.75-0 Reproducible in staging?: Yes Reproducible in production?: Yes If this was caught during regression testing, add the test name, ID and link from BrowserStack: https://test-management.browserstack.com/projects/2219752/test-runs/TR-2350/folder/13176687/41236701/1068908627 Email or phone of affected tester (no customers): [email protected] Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: iPhone 14 / iOS 26.1 App Component: User Settings
Action Performed:
Precondition: The main Expensifail account has set up Full (Expensifail) and Limit (Gmail) copilot in the Security Bug 1:
- Log in the NewDot with the Full Copilot and switch to the main account in Settings
- Navigate to the Security section
- Tap on the three dots button at the Limit Copilot
- Select Remove Copilot
Bug 2:
- Log in the NewDot with the Full Copilot and switch to the main account in Settings
- Navigate to the Security section
- Tap on the three dots button at the Full Copilot
- Select Remove Copilot
Expected Result:
A not-so-fast warning about Copilot can't remove user should display
Actual Result:
Bug 1: No warning message, and the limit copilot disappears briefly and reappears
Bug 2: The app logs out the main account and auto logs in the Full Copilot account. The switcher now displays the Limit Copilot badge, can switch to the main account, but the Full account doesn't display in the Copilot list, only the Limit account
Workaround:
Unknown
Platforms:
- [x] Android: App
- [ ] Android: mWeb Chrome
- [x] iOS: App
- [ ] iOS: mWeb Safari
- [ ] iOS: mWeb Chrome
- [x] Windows: Chrome
- [ ] MacOS: Chrome / Safari
Screenshots/Videos
https://github.com/user-attachments/assets/b22b266a-3963-420a-b23f-b8cd14ecbf8e
https://github.com/user-attachments/assets/df1ff8d2-099e-44d4-a4d4-1aba1c2834c8
Upwork Automation - Do Not Edit
- Upwork Job URL: https://www.upwork.com/jobs/~022001452701802477808
- Upwork Job ID: 2001452701802477808
- Last Price Increase: 2025-12-18
Issue Owner
Current Issue Owner: @grgia
Triggered auto assignment to @lydiabarclay (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.
Proposal
Please re-state the problem that we are trying to solve in this issue.
No warning message when "Full coplilot" removes "Limit copilot".
What is the root cause of that problem?
The Security page lets delegates open the copilot actions and run the remove flow without first checking whether the current session is a delegate. There is no guard that triggers the existing “Not so fast…” modal before removal actions start. https://github.com/Expensify/App/blob/bd180d78952816a042f7a763c99b021e784e92b0/src/pages/settings/Security/SecuritySettingsPage.tsx#L240-L334
What changes do you think we should make in order to solve the problem?
Add a delegate-session guard to every copilot removal entry point on the Security page, so acting-as-delegate sessions are stopped and shown the “Not so fast…” modal instead of attempting removals or switching accounts. Key updates:
const {isDelegateAccessRestricted, isActingAsDelegate, showDelegateNoAccessModal} = useContext(DelegateNoAccessContext);
const onPress = (e: GestureResponderEvent | KeyboardEvent) => {
if (isActingAsDelegate) {
showDelegateNoAccessModal();
return;
}
if (isEmptyObject(pendingAction)) {
showPopoverMenu(e, {email, role});
return;
}
...
};
const delegatePopoverMenuItems: PopoverMenuItem[] = [
{
text: translate('delegate.changeAccessLevel'),
onPress: () => {
if (isDelegateAccessRestricted || isActingAsDelegate) {
modalClose(() => showDelegateNoAccessModal());
return;
}
...
},
},
{
text: translate('delegate.removeCopilot'),
onPress: () => {
if (isDelegateAccessRestricted || isActingAsDelegate) {
modalClose(() => showDelegateNoAccessModal());
return;
}
...
},
},
];
<ConfirmModal
isVisible={shouldShowRemoveDelegateModal}
onConfirm={() => {
if (isActingAsDelegate) {
setShouldShowRemoveDelegateModal(false);
showDelegateNoAccessModal();
return;
}
removeDelegate({email: selectedDelegate?.email ?? '', delegatedAccess: account?.delegatedAccess});
...
}}
/>
Will review asap
Job added to Upwork: https://www.upwork.com/jobs/~022001452701802477808
Triggered auto assignment to Contributor-plus team member for initial proposal review - @truph01 (External)
Triggered auto assignment to @grgia, see https://stackoverflow.com/c/expensify/questions/7972 for more details.
❌ There was an error making the offer to @truph01 for the Reviewer role. The BZ member will need to manually hire the contributor.
@grgia Huh... This is 4 days overdue. Who can take care of this?
@ShridharGoel @grgia @truph01 @lydiabarclay this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!
@grgia Still overdue 6 days?! Let's take care of this!
The solution for this issue has been :rocket: deployed to production :rocket: in version 9.2.89-6 and is now subject to a 7-day regression period :calendar:. Here is the list of pull requests that resolve this issue:
- https://github.com/Expensify/App/pull/78110
If no regressions arise, payment will be issued on 2026-01-07. :confetti_ball:
For reference, here are some details about the assignees on this issue:
- @ShridharGoel requires payment through NewDot Manual Requests
- @truph01 requires payment through NewDot Manual Requests
@ShridharGoel / @truph01 @lydiabarclay The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]