mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-21 20:35:31 -05:00
Large number of sign-ups on public Gitea instance #14483
Open
opened 2025-11-02 11:14:08 -06:00 by GiteaMirror
·
15 comments
No Branch/Tag Specified
main
release/v1.25
release/v1.24
release/v1.23
release/v1.22
release/v1.21
release/v1.20
release/v1.19
release/v1.18
release/v1.17
release/v1.16
release/v1.15
release/v1.14
release/v1.13
release/v1.12
release/v1.11
release/v1.10
release/v1.9
release/v1.8
v1.25.3
v1.25.2
v1.25.1
v1.25.0
v1.24.7
v1.25.0-rc0
v1.26.0-dev
v1.24.6
v1.24.5
v1.24.4
v1.24.3
v1.24.2
v1.24.1
v1.24.0
v1.23.8
v1.24.0-rc0
v1.25.0-dev
v1.23.7
v1.23.6
v1.23.5
v1.23.4
v1.23.3
v1.23.2
v1.23.1
v1.23.0
v1.23.0-rc0
v1.24.0-dev
v1.22.6
v1.22.5
v1.22.4
v1.22.3
v1.22.2
v1.22.1
v1.22.0
v1.23.0-dev
v1.22.0-rc1
v1.21.11
v1.22.0-rc0
v1.21.10
v1.21.9
v1.21.8
v1.21.7
v1.21.6
v1.21.5
v1.21.4
v1.21.3
v1.21.2
v1.20.6
v1.21.1
v1.21.0
v1.21.0-rc2
v1.21.0-rc1
v1.20.5
v1.22.0-dev
v1.21.0-rc0
v1.20.4
v1.20.3
v1.20.2
v1.20.1
v1.20.0
v1.19.4
v1.21.0-dev
v1.20.0-rc2
v1.20.0-rc1
v1.20.0-rc0
v1.19.3
v1.19.2
v1.19.1
v1.19.0
v1.19.0-rc1
v1.20.0-dev
v1.19.0-rc0
v1.18.5
v1.18.4
v1.18.3
v1.18.2
v1.18.1
v1.18.0
v1.17.4
v1.18.0-rc1
v1.19.0-dev
v1.18.0-rc0
v1.17.3
v1.17.2
v1.17.1
v1.17.0
v1.17.0-rc2
v1.16.9
v1.17.0-rc1
v1.18.0-dev
v1.16.8
v1.16.7
v1.16.6
v1.16.5
v1.16.4
v1.16.3
v1.16.2
v1.16.1
v1.16.0
v1.15.11
v1.17.0-dev
v1.16.0-rc1
v1.15.10
v1.15.9
v1.15.8
v1.15.7
v1.15.6
v1.15.5
v1.15.4
v1.15.3
v1.15.2
v1.15.1
v1.14.7
v1.15.0
v1.15.0-rc3
v1.14.6
v1.15.0-rc2
v1.14.5
v1.16.0-dev
v1.15.0-rc1
v1.14.4
v1.14.3
v1.14.2
v1.14.1
v1.14.0
v1.13.7
v1.14.0-rc2
v1.13.6
v1.13.5
v1.14.0-rc1
v1.15.0-dev
v1.13.4
v1.13.3
v1.13.2
v1.13.1
v1.13.0
v1.12.6
v1.13.0-rc2
v1.14.0-dev
v1.13.0-rc1
v1.12.5
v1.12.4
v1.12.3
v1.12.2
v1.12.1
v1.11.8
v1.12.0
v1.11.7
v1.12.0-rc2
v1.11.6
v1.12.0-rc1
v1.13.0-dev
v1.11.5
v1.11.4
v1.11.3
v1.10.6
v1.12.0-dev
v1.11.2
v1.10.5
v1.11.1
v1.10.4
v1.11.0
v1.11.0-rc2
v1.10.3
v1.11.0-rc1
v1.10.2
v1.10.1
v1.10.0
v1.9.6
v1.9.5
v1.10.0-rc2
v1.11.0-dev
v1.10.0-rc1
v1.9.4
v1.9.3
v1.9.2
v1.9.1
v1.9.0
v1.9.0-rc2
v1.10.0-dev
v1.9.0-rc1
v1.8.3
v1.8.2
v1.8.1
v1.8.0
v1.8.0-rc3
v1.7.6
v1.8.0-rc2
v1.7.5
v1.8.0-rc1
v1.9.0-dev
v1.7.4
v1.7.3
v1.7.2
v1.7.1
v1.7.0
v1.7.0-rc3
v1.6.4
v1.7.0-rc2
v1.6.3
v1.7.0-rc1
v1.7.0-dev
v1.6.2
v1.6.1
v1.6.0
v1.6.0-rc2
v1.5.3
v1.6.0-rc1
v1.6.0-dev
v1.5.2
v1.5.1
v1.5.0
v1.5.0-rc2
v1.5.0-rc1
v1.5.0-dev
v1.4.3
v1.4.2
v1.4.1
v1.4.0
v1.4.0-rc3
v1.4.0-rc2
v1.3.3
v1.4.0-rc1
v1.3.2
v1.3.1
v1.3.0
v1.3.0-rc2
v1.3.0-rc1
v1.2.3
v1.2.2
v1.2.1
v1.2.0
v1.2.0-rc3
v1.2.0-rc2
v1.1.4
v1.2.0-rc1
v1.1.3
v1.1.2
v1.1.1
v1.1.0
v1.0.2
v1.0.1
v1.0.0
v0.9.99
Labels
Clear labels
$20
$250
$50
$500
backport/done
💎 Bounty
docs-update-needed
good first issue
hacktoberfest
issue/bounty
issue/confirmed
issue/critical
issue/duplicate
issue/needs-feedback
issue/not-a-bug
issue/regression
issue/stale
issue/workaround
lgtm/need 2
modifies/api
modifies/translation
outdated/backport/v1.18
outdated/theme/markdown
outdated/theme/timetracker
performance/bigrepo
performance/cpu
performance/memory
performance/speed
pr/breaking
proposal/accepted
proposal/rejected
pr/wip
pull-request
reviewed/wontfix
💰 Rewarded
skip-changelog
status/blocked
topic/accessibility
topic/api
topic/authentication
topic/build
topic/code-linting
topic/commit-signing
topic/content-rendering
topic/deployment
topic/distribution
topic/federation
topic/gitea-actions
topic/issues
topic/lfs
topic/mobile
topic/moderation
topic/packages
topic/pr
topic/projects
topic/repo
topic/repo-migration
topic/security
topic/theme
topic/ui
topic/ui-interaction
topic/ux
topic/webhooks
topic/wiki
type/bug
type/deprecation
type/docs
type/enhancement
type/feature
type/miscellaneous
type/proposal
type/question
type/refactoring
type/summary
type/testing
type/upstream
Mirrored from GitHub Pull Request
No Label
topic/ui
Milestone
No items
No Milestone
Projects
Clear projects
No project
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: github-starred/gitea#14483
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @toloveru on GitHub (May 13, 2025).
Description
Hi all, I am the maintainer of git.nixmagic.com. As of late March, I have had a large amount of abusive sign-ups on my Gitea instance. Below is a screenshot of the current user list. 30 pages are from the last week alone. For now, I am immediately disabling sign-up entirely.
What I would like to do with such a large number of accounts, is to select valid accounts for exclusion and delete / ban everything else. Not sure if the web UI can do this, Linux shell is something I'm fairly comfortable with too. If there is an easier way to do it from there, please let me know. FWIW, I believe that the backend used by the Gitea instance is SQLite.
In the long term, I'll have to also either restrict sign-up, or at the very least get email verification to work properly. Currently it cannot send such verification email, and immediately marks the account as activated instead. As such, writings such as this one unfortunately do not seem to apply here.
The idea for the email component would be that it either connects to my Postfix instances for relay, or sends out the emails by itself. I think I would prefer going through Postfix. Any suggestions on documentation I could use for this? Thank you!
Screenshots
Below is the user list at page 29.

The most recent spam accounts do not have a profile description, while the older ones are.. colourful, let's call it?

Gitea Version
1.23.7
Can you reproduce the bug on the Gitea demo site?
No
Operating System
Windows 10
Browser Version
Microsoft Edge Version 136.0.3240.64 (Official build) (64-bit)
@toloveru commented on GitHub (May 13, 2025):
The configuration I currently use is in the screenshot below. I am changing

DISABLE_REGISTRATION, and restarting Gitea for now. I suppose later on I'll have to modify the settings under[mailer]too?@lunny commented on GitHub (May 13, 2025):
You can enable both email verification and captcha.
@toloveru commented on GitHub (May 13, 2025):
Right. I believe I have enabled CAPTCHA before, and it would seem that I now also have email from using the docs at Email setup and the config cheat sheet. From the looks of it, that leaves unverified accounts in the appropriate state (activated=false). I suppose it won't stop the attacks on my instance, but at least it should allow the administrative jobs for it to delete anything that follows. As for the accounts that have been created so far, I guess that's something for future toloveru to deal with.
@toloveru commented on GitHub (May 13, 2025):
As things stand now, there are still various attempts at sign-up on regular bases. They are successful, but they no longer have activated or even unrestricted status. Currently the configuration is set to have new accounts private by default, require email activation, and CAPTCHA on sign-up.
However, this is not a threat vector I'd dismiss normally. Inquiry into their services revealed that they have a Sendmail-like mail server running that can receive confirmation emails. They also have a default-ish instance of NGINX, though it does not seem to be the NGINX software's own default page. The target that these probes were ran against can be shared privately, to the security list (I'll admit, at the time of creation, I was unsure whether this qualifies as bug or security, or whether this has significance for fellow public operators).
Anyway, the Sendmail instance strongly hints at account verification not being a silver bullet here. If they're already using headless browsers to sign up, there's little stopping them from parsing emails and acting on those too.
FWIW, the instances I probed on are hosted on Hetzner, which I am aware to have a strict abuse policy. They also had default PTR records.
@toloveru commented on GitHub (May 14, 2025):
Possibly relevant SQL commands:
^D to exit from the SQLite console.
Against the current list of about 2.6k accounts, this gets rid of just about everything I'd want to get rid of.
Affected domains:
glinxy.org
dravix.org
lyvix.org
ylixo.com
juxal.org
elyquin.org
oxilv.com
hivoltz.org
elyquin.com
ivolix.com
claxyn.com
blyxen.com
ophixy.com
claxyn.org
ivolix.org
astroaxis.online
skywardhub.online
tryhike.click
astroarch.online
astroaxis.site
dontstress.online
cosmiccircuit.store
lunapixelguru.site
fruitingbodymushrooms.online
buskonavvt.us
topcompanygroup.com
anonmails.de
.site
.store
Whether that is a good thing or not, I guess that's an exercise left to the observer.
@lunny commented on GitHub (May 14, 2025):
There is a cron task to remove all unactived accounts. You can run it at admin panel.
@toloveru commented on GitHub (May 14, 2025):
That is, indeed, the future job for future toloveru. Now having filtered all these names, I guess that's next? Regular expressions did their job, what's next? How do you add such incident response to your logs? /etc/motd entry?
I do still wonder how I should address that SQLite database though... Backup and hopefully all read-only queries until I get them right?
I want to run this service with those remaining 70 records.
@toloveru commented on GitHub (May 18, 2025):
I believe to have now addressed everything I had to in the database. What I did was to copy the
data/gitea.dbfile from the Gitea server, into my laptop. I needed a copy before making changes to it anyway. Wouldn't want to work on the live database like this, would we... 😉You may want to preface this copying with disabling sign-up, I did not. But this would prevent any genuine users from making their accounts until you're done with the adjustments about to be made.
Then I opened the SQLite database on my laptop using their DB Browser for SQLite program.
Once in there, I navigated to the
usertable. Seems like the table it opens by default isaccess, that's what you'll want to change.Now that you have that table open, you can start filtering email addresses by domain. So I pasted every domain I listed in my previous comment into the email filter, and selected all the records by clicking onto the results and pressing Ctrl-A and Delete. Rinse and repeat for every domain in the list.
What I am now left with is a much cleaner database, that I then copy-pasted back into Gitea. I'll just put the command list in a screenshot below.
I have a systemd integration for my Gitea, but the idea is that the service should be stopped before inserting a new database. But only stop it once the file has been prepared to have the same properties as the original. Maybe this can be scripted to minimize downtime, I did not. Anyway, it seems to have restarted correctly and that's probably the end of it. When I went into the User Accounts section of Gitea's admin panel, the records seem to have correctly applied.
Granted, one thing I'm not sure about is whether I got everything in the database I should've. Are there any other tables that remnants of these deleted accounts could still reside in? I don't want Gitea to exert undefined behaviour over this external change.
Anyway, for the future I guess it's going to remain an issue until I prevent these punks from making new accounts altogether. It's kind of interesting to find by looking at the database results, that these spam operations may be operated by only a handful of people. One of them likes right-wing American terms, while another likes astrology terms. They are both responsible for a majority of the accounts deleted now, though the former is certainly a lot more aggressive.
My guess so far is that I may want to add these domains to my DNS RPZ zone. That way my mail servers can try to send the email, sure, but it will all result in failed deliveries. At least they should not be able to confirm their emails at all that way. Granted, it would keep bringing the user ID ticker up and I would have to regularly run that cron task to delete those accounts. I wonder if there's a better way still...
@lunny commented on GitHub (May 18, 2025):
It may result unknown problems if you changed the database manually if you don't know the tables relationships.
@toloveru commented on GitHub (May 18, 2025):
Okay, so where do I find the tables' relationships? Or can you tell me what those relationships are? Or which developer on the project do I ask instead?
This problem was not going to be solved with just the administrative UI. The project is still too incomplete for that, and so was my own deployment of it. Many things still require outside shell access. I did not update my shell environment to be that close to my jumphost's environment for nothing. Many of my other services like DHCP, DNS, mail, ... don't have that, because I barely log into them. They don't need me to.
If you want to help, then actually help. You're by no means obligated to do so, but that doesn't change me still feeling very much alone in this. And alone, I use my own experience with the shell on a host I own, in a way that I am comfortable with. If that's something you don't like, then tell me how you would've addressed the problem - in its full scope - instead.
@techknowlogick commented on GitHub (May 18, 2025):
@toloveru to clarify your situation, you are looking at bulk-removing accounts based on specific email domains? And those domains contain no legitimate users? If so, I have a bash script that I used for gitea.com that does that, and then before running it I add those domains to the email block list that I could share with you
@toloveru commented on GitHub (May 18, 2025):
Precisely! These domains are what I am trying to target for bulk removal, I have reasonable confidence that none of those users are legitimate. If you'd like to share what you've done for the gitea.com instance (which I'd imagine to receive even more of these), much appreciated! What I'd be particularly interested in is the domain list, database implementation (i.e. SQLite, MariaDB/MySQL, ...), and which parts of the database are being targeted for this purpose.
Also, how does their presence affect certain fields in the database? When I look at field
idunderuser, it's at 3365 when I received the initial database. Is there a limit to that number, and what happens if/when it overflows? Or is the max value large enough to make it irrelevant?Just now I also looked into the source code for Gitea, and came across the following bits that may be able to tell me more about how Gitea does it in the administrative UI. However, my experience with Go is limited and I couldn't seem to get to concrete database calls... All I managed to deduce so far is that my (admittedly somewhat chainsaw) approach did not consider existing repositories for these users, the Go code does seem to be doing that. A bash script meanwhile would be right up my alley!
e2277d07ca/services/cron/tasks_extended.go (L23-L35)d89eed998f/services/user/user.go (L280-L284)@techknowlogick commented on GitHub (May 18, 2025):
@toloveru here is the portion of the script I use for this purpose: https://gist.github.com/techknowlogick/c2f0a91620aad747a8e226f0b1b5a484
I lock the accounts and mark them as private first, and then go through them later on, but I added a delete function in case you don't want to deal with that intermediary step. You could remove the CLI prompt (asking for a
Yfor each account) to loop through everything without intervention instead.@ktwrd commented on GitHub (May 19, 2025):
@toloveru All the primary keys use
int64as the type, which is a signed(?) 64bit integer. The limit for a signed 64bit integer is9,223,372,036,854,775,807.@toloveru commented on GitHub (May 19, 2025):
@techknowlogick Sweet, thank you for having shared that! I like how it uses the Gitea API, that way the database schema can remain under the application's control (and remain adjustable by its developers - you - long-term without me needing to keep track of it). Also seems a lot safer than directly adjusting the database, I'll try to integrate that into my instance as well.
@ktwrd Thank you for mentioning that! 64-bit (either signed or unsigned) should definitely be large enough to make it irrelevant yeah. It popped into my mind because I've been working a lot with Arduino recently, that uses 16-bit.. its 65536 range is not that much to work with. But 64 on the other hand, exponentially enormous! I guess it won't be an issue anytime soon then. That's a relief 😌