From a6c8ce32c33628ead196f8fb7a3ed2b1d0ad2706 Mon Sep 17 00:00:00 2001 From: Brian Gough Date: Wed, 6 May 2026 11:59:04 +0100 Subject: [PATCH] Merge pull request #33312 from overleaf/copilot/send-clear-site-data-header Send `Clear-Site-Data` header on account deletion GitOrigin-RevId: c3f0b5f27cc80a1927518c56436c3a808b144fb7 --- .../app/src/Features/User/UserController.mjs | 3 +++ .../web/test/acceptance/src/DeletionTests.mjs | 18 ++++++++++++++++++ .../test/unit/src/User/UserController.test.mjs | 11 +++++++++++ 3 files changed, 32 insertions(+) diff --git a/services/web/app/src/Features/User/UserController.mjs b/services/web/app/src/Features/User/UserController.mjs index 73f7ed4c06..ac88451221 100644 --- a/services/web/app/src/Features/User/UserController.mjs +++ b/services/web/app/src/Features/User/UserController.mjs @@ -293,6 +293,9 @@ async function tryDeleteUser(req, res, next) { UserSessionsManager.promises.untrackSession(user, sessionId).catch(err => { logger.warn({ err, userId: user._id }, 'failed to untrack session') }) + // Note that the "*" must be in double quotes + // https://www.w3.org/TR/clear-site-data/#ref-for-grammardef- + res.set('Clear-Site-Data', '"*"') res.sendStatus(200) } diff --git a/services/web/test/acceptance/src/DeletionTests.mjs b/services/web/test/acceptance/src/DeletionTests.mjs index da4b832818..106b18ab06 100644 --- a/services/web/test/acceptance/src/DeletionTests.mjs +++ b/services/web/test/acceptance/src/DeletionTests.mjs @@ -137,6 +137,24 @@ describe('Deleting a user', function () { }) }) + it('Should send the Clear-Site-Data header', function (done) { + this.user.getCsrfToken(error => { + expect(error).not.to.exist + this.user.request.post( + { + url: '/user/delete', + json: { password: this.user.password }, + }, + (error, response) => { + expect(error).not.to.exist + expect(response.statusCode).to.equal(200) + expect(response.headers['clear-site-data']).to.equal('"*"') + done() + } + ) + }) + }) + describe('when scrubbing the user', function () { beforeEach(function (done) { this.user.get((error, user) => { diff --git a/services/web/test/unit/src/User/UserController.test.mjs b/services/web/test/unit/src/User/UserController.test.mjs index b3c05450e0..eca0c4952d 100644 --- a/services/web/test/unit/src/User/UserController.test.mjs +++ b/services/web/test/unit/src/User/UserController.test.mjs @@ -243,6 +243,7 @@ describe('UserController', function () { status: sinon.stub(), sendStatus: sinon.stub(), json: sinon.stub(), + set: sinon.stub(), } ctx.res.status.returns(ctx.res) ctx.next = sinon.stub() @@ -270,6 +271,16 @@ describe('UserController', function () { }) }) + it('should set the Clear-Site-Data header', function (ctx) { + return new Promise(resolve => { + ctx.res.sendStatus = code => { + expect(ctx.res.set).to.have.been.calledWith('Clear-Site-Data', '"*"') + resolve() + } + ctx.UserController.tryDeleteUser(ctx.req, ctx.res, ctx.next) + }) + }) + it('should try to authenticate user', function (ctx) { return new Promise(resolve => { ctx.res.sendStatus = code => {