0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-27 22:49:56 -05:00

Fixed Editors being able to invite Editors (#19904)

ref ENG-774
ref https://linear.app/tryghost/issue/ENG-774

Staff Tokens will have both a `user` and an `apiKey` present on the
`loadedPermissions`.

The check here for `apiKey` was written when we could assume that an
`apiKey` was an Admin Integration - so it completely overwrote the
previous `allowed` list. When we added the concept of Staff Tokens -
this resulted in a privilege escalation.

This is a good lesson in not using proxies or indicators for data, as
changes elsewhere can invalidate them - if we had been specific and
checked the role of the current actor we wouldn't've had this bug!
This commit is contained in:
Fabien 'egg' O'Carroll 2024-03-26 00:45:08 +07:00 committed by GitHub
parent 471492d966
commit 3d3b3ff701
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 16 additions and 2 deletions

View file

@ -93,8 +93,7 @@ Invite = ghostBookshelf.Model.extend({
} else if (_.some(loadedPermissions.user.roles, {name: 'Editor'})) {
allowed = ['Author', 'Contributor'];
}
}
if (loadedPermissions.apiKey) {
} else if (loadedPermissions.apiKey) {
allowed = ['Editor', 'Author', 'Contributor'];
}

View file

@ -153,6 +153,21 @@ describe('Unit: models/invite', function () {
});
});
it('invite editor with staff token', function () {
loadedPermissions.apiKey = {
roles: [{name: 'Admin Integration'}]
};
sinon.stub(models.Role, 'findOne').withArgs({id: 'role_id'}).resolves(roleModel);
roleModel.get.withArgs('name').returns('Editor');
return models.Invite.permissible(inviteModel, 'add', context, unsafeAttrs, loadedPermissions, true, true, true)
.then(Promise.reject)
.catch((err) => {
(err instanceof errors.NoPermissionError).should.eql(true);
delete loadedPermissions.apiKey;
});
});
it('invite author', function () {
sinon.stub(models.Role, 'findOne').withArgs({id: 'role_id'}).resolves(roleModel);
roleModel.get.withArgs('name').returns('Author');