Roundup Tracker - Issues

Issue 2551432

classification
Numeric local-part in emails causes username/ID mixups
Type: crash Severity: normal
Components: Web interface Versions:
process
Status: open
:
: : ber, rouilj, schlatterbeck, wilsj
Priority: :

Created on 2026-09-30 15:15 by wilsj, last changed 2026-10-15 16:37 by rouilj.

Messages
msg8534 Author: [hidden] (wilsj) Date: 2026-09-30 15:15
We have seen an influx of new Chinese `[0-9]+@qq.com` mailing our Roundup instance lately.

When mailgw creates a new user for one of these addresses, the username based on the local part 
becomes completely numerical. This in turn causes crashes when clicking the Submit button 
issue.item.html, as the values in `creator`, `nosy`, etc. are treated as IDs instead of numerical 
usernames:

  <class 'IndexError'>: no such user 123456789

Besides the crashing when trying to update an issue, there is also a risk that a user with an actual 
numerical ID matching the username already exists. I suspect such a scenario could result in all 
sorts of interesting recipient mixups.

I am aware of the existence of `try_id_parsing='no'`. Unfortunately, these cannot be set for 
properties that are built into the `IssueClass` type (such as `nosy`).

I see two possible solutions to this:

1. Modify mailgw's username generation to prefix the resulting numerical usernames with a letter.

2. Modify the template userauditors to add a letter to the username before inserting it into the 
database.

Before fixing this in our instance, I'd be curious to hear which, if any, of the proposed solutions 
would be preferred by upstream.
msg8536 Author: [hidden] (rouilj) Date: 2026-10-01 16:54
Reposting using roundup rather than email because of an old since fixed bug.
Sorry for the duplicate.

Hi William:

 I added Ralf and Bern (other devs) to this discussion.

On Wed, Sep 30, 2026 at 11:15 AM William Sjöblom
<issues@roundup-tracker.org> wrote:
> We have seen an influx of new Chinese `[0-9]+@qq.com` mailing our Roundup instance lately.
>
> When mailgw creates a new user for one of these addresses, the username based on the local 
part
> becomes completely numerical. This in turn causes crashes when clicking the Submit button
> issue.item.html, as the values in `creator`, `nosy`, etc. are treated as IDs instead of 
numerical
> usernames: [...]
> I am aware of the existence of `try_id_parsing='no'`. Unfortunately, these cannot be set for
> properties that are built into the `IssueClass` type (such as `nosy`).

If these are spam, then: https://wiki.roundup-tracker.org/AntiSpam and
https://wiki.roundup-tracker.org/SpamBayesIntegration may be useful.

try_id_parsing can be set, for nosy and default other non-protected
properties, but is
poorly documented. We can document this.

However protected (auditing) properties ( "creation", "creator",
"activity" or "actor") can not have
new definitions assigned in schema.py. But I think (and saw in one
place in the code) the protected
properties only see internal database IDs (e.g. the 20 in user20). I
don't think they are ever
exposed to the username or other user supplied data.

Ralf, Bern does this sound correct?

However William, you said "creator" reports a problem, but you
shouldn't (AFAIK) be able to set creator
from the web interface (raises an error as a protected property) or
anywhere else except direct database
manipulation. Can you verify it's creator that is failing, what the
error is, and how are you trying to set creator?

> I see two possible solutions to this:
>
> 1. Modify mailgw's username generation to prefix the resulting numerical usernames with a 
letter.
> 2. Modify the template userauditors to add a letter to the username before inserting it into 
the
> database.
>
> Before fixing this in our instance, I'd be curious to hear which, if any, of the proposed 
solutions
> would be preferred by upstream.

Neither, but not having users with purely numeric email addresses
would be best 8-). But that's not
something we can control.

To address nosy, you can change your IssueClass to add:

    IssueClass(db,"issue", ...,
     nosy=Multilink("user", do_journal="no", try_id_parsing="yes"),
     ...)

and similar for other link/multilinks to the user class. AFAIK this
should not be a problem, but I suggest
backing up the db for safety just in case.

This ability is "documented" in
https://www.roundup-tracker.org/docs/upgrading-history.html#journalling-changes
at the end of the section (look for nosy). The up side is that you
don't have to do username munging. The down
side is that changes are scattered across properties in the schema,
but does use the override mechanism
Richard developed to handle this case.

AFAICT the override mechanism not documented anywhere else. William,
where were you looking for info on
solving your problem?

I was thinking describing this mechanism in the references.txt published as
https://www.roundup-tracker.org/docs/reference.html#classes-and-properties-creating-a-new-
information-store
section just before the Methods section header. The other place I
could document it is in the IssueClass section
(the section after Methods).

However, Bern and Ralf, I'm wondering if we could simplify this. The
"try_id_parsing" option appears to be
a class-level setting rather than a property-level one that points to
the class. I can't think of a situation
where different Link() or MultiLink() properties pointing to the same
class would need different "try_id_parsing"
values.

I suggest adding a `_try_id` property (default True) to class Class
and Class.settryid(enabled) Class.tryid()
(alternate name suggestions welcome) methods similar to
setorderprop/orderprop etc. The default value
of try_id_parsing for any properties pointing to that class will use
the _try_id value.

Ralf you added try_id_parsing, so thoughts?

For William's case, calling `user.try_id(False)` will make any
property that points to the user class default to
try_id_parsing=no. Calling Class(.., try_id_parsing=True/False) will
explicitly set the value overriding the default.

So one addition to schema.py "fixes" all the references he has to the
user class.

Quips, comments, evasions, questions or answers?

--rouilj
msg8542 Author: [hidden] (rouilj) Date: 2026-10-07 15:34
Looks like another encoding bounce issue. Ralf on Oct 1, 2026, 1:28 PM said:

On Thu, Oct 01, 2026 at 04:41:38PM +0000, John Rouillard wrote:
>  I added Ralf and Bern (other devs) to this discussion.
>
> On Wed, Sep 30, 2026 at 11:15 AM William Sjoblom
> <issues@roundup-tracker.org> wrote:
> > We have seen an influx of new Chinese `[0-9]+@qq.com` mailing our Roundup instance lately.
> >
> > When mailgw creates a new user for one of these addresses, the
> > username based on the local part becomes completely numerical.

This seems to be the problem. Fully numeric properties confuse the
parser because they are taken for IDs in the database. So when you input
a numeric username it will think its the ID.

> However William, you said "creator" reports a problem, but you
> shouldn't (AFAIK) be able to set creator
> from the web interface (raises an error as a protected property) or
> anywhere else except direct database
> manipulation. Can you verify it's creator that is failing, what the
> error is, and how are you trying to set creator?

I think when e.g. trying to search for creator or some other property
that is a Link/Multilink to the user class with a fully-numerical
username will confuse the parser. So it thinks you're searching for the
creator being user12345 when in fact you're searching for the user with
the *username* 12345.

> > I see two possible solutions to this:
> >
> > 1. Modify mailgw's username generation to prefix the resulting
> >    numerical usernames with a letter.
> > 2. Modify the template userauditors to add a letter to the username before inserting it 
into the
> > database.

Maybe we can create a configurable template for user creation via
mailgw. This could add a prefix or suffix and/or mandate the use of the
full email address for the username. I think many web services today use
the email address for good reasons...

> However, Bern and Ralf, I'm wondering if we could simplify this. The
> "try_id_parsing" option appears to be
> a class-level setting rather than a property-level one that points to
> the class. I can't think of a situation
> where different Link() or MultiLink() properties pointing to the same
> class would need different "try_id_parsing"
> values.

Yes, I think so, too in the meanwhile, I was unsure when I implemented
this as a Link/Multilink property.

> I suggest adding a `_try_id` property (default True) to class Class
> and Class.settryid(enabled) Class.tryid()
> (alternate name suggestions welcome) methods similar to
> setorderprop/orderprop etc. The default value
> of try_id_parsing for any properties pointing to that class will use
> the _try_id value.

Why not also call it 'try_id_parsing'? It would be the default for
Link/Multilink properties to that class but an explicit Link property
would win over this default?

> For William's case, calling `user.try_id(False)` will make any
> property that points to the user class default to
> try_id_parsing=no. Calling Class(.., try_id_parsing=True/False) will
> explicitly set the value overriding the default.

Yes, I think that would be nice.

> So one addition to schema.py "fixes" all the references he has to the
> user class.

It has other problems, though, in the API you can no longer search for
user IDs when this is turned off.
msg8544 Author: [hidden] (rouilj) Date: 2026-10-07 15:45
Ralf said:

> Maybe we can create a configurable template for user creation via
> mailgw. This could add a prefix or suffix and/or mandate the use of the
> full email address for the username. I think many web services today use
> the email address for good reasons...

There is a patch that allows somebody to login using their primary or secondary
email address (https://wiki.roundup-tracker.org/LoginWithEmail).

However, we don't obscure the username in templates etc. If we used email as username we
would need to do something to the templates (or the plain() method at least) to obscure/
filter an email address used as a username.

> > [rouilj]
> > So one addition to schema.py 'fixes' all the references he has to the
> > user class.
>
> It has other problems, though, in the API you can no longer search for
> user IDs when this is turned off.

Could you describe this issue more? How does setting a properties' try_id_parsing
prop affect searching? Wouldn't the filter spec property name:
    id=12345
vs.
    username=12345

cause try_id_parsing to be skipped as id only accepts id's and username only supports names?
You don't have the ambiguity in the API that you do in the edit field in the web interface.

-- rouilj

(P.S. The umlauted o in William's last name is tripping the unicode failure.)
msg8545 Author: [hidden] (wilsj) Date: 2026-10-08 08:10
John:
> If these are spam, then: https://wiki.roundup-tracker.org/AntiSpam and
> https://wiki.roundup-tracker.org/SpamBayesIntegration may be useful.

They seemingly are not, which is why I thought it worth raising this issue in
the first place. QQ mail, with its numerical local parts, seems to be one of the
most popular domestic Chinese email providers.

John:
> However William, you said "creator" reports a problem, but you shouldn't
> (AFAIK) be able to set creator from the web interface (raises an error as a
> protected property)

You are correct. I mixed it up with "initiator", a custom Link to user in our
schema, when drafting the initial email. I'll set try_id_parsing="no" on initiator
and nosy in our schema for now.

John:
> William, where were you looking for info on solving your problem?

https://www.roundup-tracker.org/docs/reference.html. try_id_parsing is described
there, but the docs say IssueClass automatically includes nosy, so I wrongly
assumed its attributes couldn't be changed. A note next to that sentence saying
the built-in properties can be redefined in schema.py would have saved me.

Ralf:
> Maybe we can create a configurable template for user creation via
> mailgw. This could add a prefix or suffix and/or mandate the use of the
> full email address for the username.

John:
> I suggest adding a `_try_id` property (default True) to class Class

I'm not sure which way forward is best. A class-level try_id_parsing would fix our
case with a couple of lines in schema.py, while a mailgw username template would
avoid creating ambiguous usernames in the first place. What I want to underline
is that addresses in this format are in active use and in many cases completely
legitimate. Since the stock templates break on them out of the box, I think it's
worth tracking either way.
msg8546 Author: [hidden] (schlatterbeck) Date: 2026-10-08 13:41
On Wed, Oct 07, 2026 at 03:45:31PM +0000, John Rouillard wrote:
> > It has other problems, though, in the API you can no longer search for
> > user IDs when this is turned off.
> 
> Could you describe this issue more? How does setting a properties'
> try_id_parsing prop affect searching? Wouldn't the filter spec
> property name:
>     id=12345
> vs.
>     username=12345

It's when you're searching for a Link or Multilink property to user,
e.g. creator of an issue:

https://tracker/path/issue?:filter=creator&creator=username

Normally (when try_id_parsing is set) you can specify the ID or the key
property (username) of the creator you're searching for.

When try_id_parsing is False you can no longer use the ID and numeric
values will be interpreted as the key property. Note that the same
applies in the REST-API.

Kind regards
Ralf
-- 
Dr. Ralf Schlatterbeck                  Tel:   +43/2243/26465-16
Open Source Consulting                  www:   www.runtux.com
Reichergasse 131, A-3411 Weidling       email: office@runtux.com
msg8553 Author: [hidden] (rouilj) Date: 2026-10-12 19:53
Hi William:

I have updated the IssueClass section of the docs to read:

====
IssueClass
~~~~~~~~~~

IssueClass automatically includes the "messages", "files", "nosy", and
"superseder" properties. You can override the default configuration of
these properties by defining them in your IssueClass. For example::

  issue = IssueClass(..., nosy=Multilink("user",
                     try_id_parsing="no"), ...)

would disable id parsing forcing lookup by username even if the
username is numeric.

The messages and files properties list the links to the messages and
files related to the issue. The nosy property is a list of links to
users to tell about changes to the issue. They get "CC'ed"
====

Is that sufficient?

> I'm not sure which way forward is best. A class-level try_id_parsing
would fix our
> case with a couple of lines in schema.py,

Given the search issue that Ralf brought up, I wonder if this is a good
idea. Maybe
we should add some friction to using try_id_parsing.

> while a mailgw username template would
> avoid creating ambiguous usernames in the first place. What I want to
underline
> is that addresses in this format are in active use and in many cases
completely
> legitimate. Since the stock templates break on them out of the box, I
think it's
> worth tracking either way.

You don't need a template, we could add an auditor for create and set on
the user class.
It would:

  1) on create change an all numeric username to some value (e.g. add
the first element
     of the domain and an underscore as a prefix (12345@qq.com ->
qqa_12345), If the username
     is unique, set the returned username prop accordingly. If not
unique, add some salt to
     the name until it is unique.

  2) on set, raise an exception that the username is not acceptable.

implementation thoughtfully considered 8-).

The user will have to be notified of their username. I am not sure we
have a notifier or
anything to do that. If the user only communicates via email, it's not
an issue.

I am not sure what happens if two different joes: joe@somewhere.com and
joe@overthere.com
both email the tracker. Can't have two 'joe' usernames. This argues for
the auditor and not
just a template to create a unique name. On the web, you are just told
to choose a new name
and associate your email with it. Over email that's not possible.

I think this is a better way to handle it than adding try_id_parsing to
the class.

Ralf thoughts?
msg8559 Author: [hidden] (rouilj) Date: 2026-10-15 16:37
> I am not sure what happens if two different joes: joe@somewhere.com
and
> joe@overthere.com both email the tracker.

You get joe and joe1 (assuming joe1 exists, otherwise joe2, 3 ....).

I checked and the user creation process triggers auditors, so adding an
auditor with

  db.user.audit('create', modify_numeric_usernames, priority=90)

should run modify_numeric_usernames before the tracker supplied user
auditors.

Similarly you can prevent setting the username to a pure number with a
set auditor.

Ralf, what are your thoughts on including something like this in the
default auditor?
By default it would add an alphabetic suffix (a,b,c,d...aa, ab...) to
any pure numeric
username. We can set a flag in detectors/config.ini to easily disable
the feature to allow
pure numeric usernames.
History
Date User Action Args
2026-10-15 16:37:12rouiljsetmessages: + msg8559
2026-10-12 19:53:58rouiljsetmessages: + msg8553
2026-10-08 13:41:22schlatterbecksetmessages: + msg8546
2026-10-08 08:10:44wilsjsetmessages: + msg8545
2026-10-07 15:45:29rouiljsetmessages: + msg8544
2026-10-07 15:34:28rouiljsetmessages: + msg8542
2026-10-01 16:54:55rouiljsetnosy: + rouilj
messages: + msg8536
2026-10-01 13:04:42rouiljsetstatus: new -> open
nosy: + schlatterbeck, ber
2026-09-30 15:15:31wilsjcreate