This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch db/8607 in repository https://gitbox.apache.org/repos/asf/allura.git
commit b77f66002d3adf3eae404988aef9a3874dd63db4 Author: Dave Brondsema <[email protected]> AuthorDate: Fri May 15 16:51:36 2026 -0400 [#8607] check app_config_id in update_forums --- ForgeDiscussion/forgediscussion/forum_main.py | 5 ++- .../tests/functional/test_forum_admin.py | 36 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/ForgeDiscussion/forgediscussion/forum_main.py b/ForgeDiscussion/forgediscussion/forum_main.py index 9ab89f4c6..2c70cd47b 100644 --- a/ForgeDiscussion/forgediscussion/forum_main.py +++ b/ForgeDiscussion/forgediscussion/forum_main.py @@ -322,7 +322,10 @@ def set_value(forum, name, val): setattr(forum, name, val) for f in forum: - forum = DM.Forum.query.get(_id=ObjectId(str(f['id']))) + forum = DM.Forum.query.get(_id=ObjectId(str(f['id'])), + app_config_id=self.app.config._id) + if forum is None: + continue if f.get('delete'): forum.deleted = True M.AuditLog.log('deleted forum "{}" from {}'.format( diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py index 72cf633d5..459f2c91a 100644 --- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py +++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum_admin.py @@ -18,9 +18,12 @@ import logging import re +from ming.odm import ThreadLocalODMSession +from tg import tmpl_context as c from alluratest.controller import TestController from allura.lib import helpers as h from allura import model as M +from allura.tests import decorators as td from forgediscussion import model as FM @@ -320,3 +323,36 @@ def test_footer_monitoring_email(self): 0].kwargs['text'], email_tasks[0].kwargs['text'] assert 'a project admin can change settings at http://localhost/p/test/admin/discussion/forums' in email_tasks[ 0].kwargs['text'] + + @td.with_tool('test2', 'Discussion', 'discussion') + def test_update_forums_rejects_foreign_forum(self): + # Create a forum in the test2 project's Discussion app (the victim). + h.set_context('test2', 'discussion', neighborhood='Projects') + victim_app_config_id = c.app.config._id + victim = FM.Forum( + app_config_id=victim_app_config_id, + shortname='victim', + name='Victim Forum', + description='original', + ) + ThreadLocalODMSession.flush_all() + victim_id = victim._id + + # Attacker is admin of project 'test' and posts to its update_forums with the victim's _id. + self.app.post('/admin/discussion/update_forums', + params={'forum-0.delete': 'on', + 'forum-0.id': str(victim_id), + 'forum-0.name': 'Pwned', + 'forum-0.shortname': 'pwned', + 'forum-0.description': 'pwned', + 'forum-0.monitoring_email': ''}) + + # Victim forum in test2 must be untouched. + ThreadLocalODMSession.close_all() + h.set_context('test2', 'discussion', neighborhood='Projects') + reloaded = FM.Forum.query.get(_id=victim_id) + assert reloaded is not None + assert reloaded.deleted is False, 'foreign forum was deleted via cross-project update_forums' + assert reloaded.name == 'Victim Forum', 'foreign forum was renamed via cross-project update_forums' + assert reloaded.description == 'original' + assert reloaded.app_config_id == victim_app_config_id
