Opened 11 years ago

Closed 11 years ago

Last modified 11 years ago

#203 closed enhancement (fixed)

[PATCH]: Allow restricting ticket updates to ticket participants

Reported by: kris@… Owned by: bas
Priority: major Milestone: Version 1.5.0
Component: email2trac Version: trunk
Keywords: Cc:


USE CASE: I use email2trac to integrate an internal instance of Trac with traditional user support ticketing via email. This is great, because it keeps both internal and external issues under the same roof. Users simply send in their support requests via e-mail and email2trac + Trac notifications handle the rest while keeping Trac itself restricted. [ Parenthetically, by use of tags and an outgoing filter in the MTA, external tickets can also have internal comments allowing us to define which updates are to be sent out externally. This would of course be better to implement in the Trac layer, but it does the job. ]

PROBLEM: With ticket_update on, email2trac allows any ticket to be updated by just changing the ticket number in the Subject. While great for an open Trac, it opens a security hole when Trac is used for private ticketing. Example:

1) mike@… has a ticket #453: Someone hijacked my account

2) steve@… sends a random email with the same ticket number, eg. #453: Sneak me in which appends his comment to a ticket he should have no access to. If always_notify_updater is on, it will also add him to the notification list. The sender anomaly is easy to miss and scanning for it a needless mental burden. Obviously, the intent may not even be malicious, eg. Steve may have corrupted the Subject line by accident.

PATCHED BEHAVIOR: by turning on ticket_update_restricted_to_participants, a ticket update is allowed only if 1) the updater is the reporter, 2) the updater is in the CC or 3) the updater matches a Trac username (i.e. is staff). If the update is denied, a new ticket will be generated instead as to not loose the issue (NOTE: the current trunk will drop any e-mail that has a ticket number which does not match a ticket; this patch also fixes that as a side-effect).

---    (revision 375)
+++    (working copy)
@@ -197,6 +197,11 @@
                        self.TICKET_UPDATE = 0

+               if parameters.has_key('ticket_update_restricted_to_participants'):
+                       self.TICKET_UPDATE_RESTRICTED_TO_PARTICIPANTS = int(parameters['ticket_update_restricted_to_participants'])
+               else:
+                       self.TICKET_UPDATE_RESTRICTED_TO_PARTICIPANTS = 0
                if parameters.has_key('ticket_update_by_subject'):
                        self.TICKET_UPDATE_BY_SUBJECT = int(parameters['ticket_update_by_subject'])
@@ -762,6 +767,42 @@
               = None
                        return False

+                       # Is the updater the reporter?
+                       # Since all Trac users are allowed to update, it does
+                       # not matter if any of our fields contain usernames
+                       # instead of emails.
+                       #
+                       if tkt['reporter'] and self.email_addr.lower() == tkt['reporter'].lower():
+                               if self.DEBUG:
+                                       print 'Restricted update: ALLOW, %s is the ticket reporter' %(self.email_addr)
+                       # Is the updater in the CC?
+                       elif tkt['cc'] and self.email_addr.lower() in tkt['cc'].lower().replace(' ', '').split(','):  # assuming space is fragile, hence replace()
+                               if self.DEBUG:
+                                       print 'Restricted update: ALLOW, %s is in the CC' %(self.email_addr)
+                       else:
+                               tkt_allow_update = False
+                               # Is the update a Trac user?
+                               for username, name, email in self.env.get_known_users():
+                                       if email and email.lower() == self.email_addr.lower():
+                                               tkt_allow_update = True
+                                               if self.DEBUG:
+                                                       print 'Restricted update: ALLOW, %s matches username %s' %(self.email_addr, username)
+                                               break
+                               # No luck? Fail the update.
+                               if not tkt_allow_update:
+                                       if self.DEBUG:
+                                               print 'Restricted update: DENIED, %s does not match a username nor is it the reporter or in the CC' %(self.email_addr)
+                              = None
+                                       return False
                # How many changes has this ticket
                cnum = len(tkt.get_changelog())

@@ -1486,7 +1527,11 @@
                        if'reply') and self.TICKET_UPDATE:
                                self.system = 'ticket'
-                               self.ticket_update(m,'reply'), spam_msg)
+                               result = self.ticket_update(m,'reply'), spam_msg)
+                               # If the ticket was not found, create a new one instead of loosing it
+                               if not result:
+                                       self.new_ticket(m, subject, spam_msg)

                        # New ticket + fields

Looking forward to seeing whether you think this is something that should go into the release. The patch itself is rather verbose due to the debugging. FWIW this was also my first foray into Python, apologies if the patch is not very Pythonic. :)

Thanks a lot for your efforts, keep up the great work!


Attachments (0)

Change History (6)

comment:1 Changed 11 years ago by bas

  • Status changed from new to assigned

Thanks for the patch and comments. I am just back from a short break. I will look into it and combine it wirh #202

comment:2 Changed 11 years ago by Dennis McRitchie <dmcr@…>

I would also add that the list of allowed updaters should include the owner of the ticket. So to summarize this along with #202, the reporter must have TICKET_CREATE permission to create the ticket; and the reporter, owner, CC member, or Trac user must have TICKET_MODIFY permission to update the ticket. Else, 'anonymous' must have the necessary permission.


comment:3 Changed 11 years ago by bas

Can i ask to attach the patch to this ticket. So i can download it

comment:4 Changed 11 years ago by bas

(In [397]) implement permission system for ticket. Added

  • None
  • trac permission model, see #202, #203

comment:5 Changed 11 years ago by bas

  • Resolution set to fixed
  • Status changed from assigned to closed

(In [398]) Added permission check system, closes #202, #203.

  • can be activated by setting ticket_permission_system:
    • ticket_permission_system: trac
    • ticket_permission_system: update_restricted_to_participants

If it is set to trac it will honour the settings that are set in the trac system.

If 'update_restricted_to_participants' is choosen then a ticket update is allowed only if:

1) the updater is the reporter, 2) the updater is in the CC 3) the updater has trac permission to update the ticket.

If the update is denied, a new ticket will be generated instead as to not loose the issue .

comment:6 Changed 11 years ago by bas

  • Milestone set to Version 1.5.0

Add Comment

Modify Ticket

Change Properties
as closed The owner will remain bas.
The resolution will be deleted. Next status will be 'reopened'.

E-mail address and user name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.