Last Thursday, May 7th 2026, we discovered an attempt to add malicious code in packages in the Plone collective. This is similar to an earlier attack in January.
Someone who had write access to the collective got hacked, and his account was used for an attack. We have removed this user from the Collective.
This time about 166 packages were affected. In most cases extra code was added in directories .vscode and public. We don't know exactly what the code does. But the goal seems to be to steal crypto wallets when you open such a package in the Visual Studio Code editor.
End users would not be affected, only developers working on these repositories.
It seems to be the "PolinRider" attack, or a very similar one, described here:
An example is this commit to zestreleaser.towncrier. I made the original commit myself in December, but this week someone changed the commit, and added the bad files.
We have gotten rid of the bad code in all affected repositories. In a few cases we did our own force push to restore the original commit. In most cases we simply removed the .vscode and public directories and did a normal push. See for example this commit.
Two things may have gone wrong:
- Maybe the
.vscodeandpublicdirectories already existed and contained valid code. In that case, individual package maintainers can bring the good code back themselves from a previous commit. - The force pushes also added two lines to
.gitignore:temp_auto_push.batandtemp_interactive_push.bat. That part is not dangerous, but you can still remove them if you are a maintainer. It seemed less important to try to clean that up as well, than it was to remove the actually bad code.
In January we added organisation-wide branch protection rulesets on the plone GitHub org to prevent force pushes like this. Unfortunately rulesets are not available organisation-wide on the collective GitHub org. Last week we added protective rulesets on each of the affected repositories. Today we have added these for all existing repositories in the collective.
Note that we have setup the rulesets so that you cannot force push to the default branch (usually main or master) and to branches that match our usual maintenance pattern [0-9]*.x. So if you create a branch called feature, and make a PR (pull request) of this, you can still force push a change, and this is useful. Potential attackers could also do this though. If a force push happens in a PR, GitHub shows a note about this in the PR, so be careful when you see such a note, and inspect the changes.
When you add a new repository to the collective, you should add these rulesets yourself.
For the list of repositories, and the main script that we used to add the rulesets, see Script to add and check standard branch/tag rulesets on GitHub · GitHub
Maurits van Rees
Plone Security Team
Here is the list of affected repositories as well. (I tried to include the script here, but it did not show up nicely.)
Affected repos
collective-referencecontent collective-searchblocks collective.address collective.ajaxify collective.anotherdynamicgroupsplugin collective.auditlog collective.beaker collective.behavior.talcondition collective.big.bang collective.catalogtrace collective.checklist collective.ckeditor collective.ckeditortemplates collective.classschedule collective.click_to_zoom collective.collectionepilog collective.collectionfilter collective.contact.core collective.contact.plonegroup collective.contactformprotection collective.contentrules.setfield collective.contentsections collective.cron collective.customizedstaticresources collective.datatablesviews collective.datepickerpattern collective.deletepermission collective.dms.basecontent collective.dms.batchimport collective.dms.mailcontent collective.dms.scanbehavior collective.documentgenerator collective.eeafaceted.collectionwidget collective.eeafaceted.dashboard collective.eeafaceted.z3ctable collective.excelexport collective.exportimport.examples collective.externalimageeditor collective.externallinkfilter collective.faq collective.formsupport.counter collective.ftw.tokenauth collective.ftw.upgrade collective.ftwslacker collective.generic.devmode collective.generic.skel collective.generic.webbuilder collective.geolocationbehavior collective.gridlisting collective.html2blocks collective.iconifiedcategory collective.imagemaps collective.immediatecreate collective.impersonate collective.js.backbone collective.js.chosen collective.js.datatables collective.js.tooltipster collective.js.underscore collective.jsconfiguration collective.keycdn collective.labels collective.ldapsetup collective.localstyles collective.markdownplus collective.mockmailhost collective.pdbpp collective.portlet.embed collective.portlet.relateditems collective.pwexpiry collective.querynextprev collective.quickupload collective.recipe.omelette collective.restapi.easyform collective.revisionmanager collective.richdescription collective.sendinblue collective.sidebar collective.sitter collective.solr collective.splitsitemap collective.tiles.advancedstatic collective.tiles.carousel collective.timestamp collective.translators collective.transmute collective.vectorsearch collective.venue collective.volto.contactsblock collective.volto.dropdownmenu collective.volto.footer collective.volto.formsupport collective.volto.gdprcookie collective.volto.otp collective.volto.secondarymenu collective.volto.sections collective.volto.slimheader collective.volto.subfooter collective.webhook collective.wfadaptations collective.workspace collective.xkey collective.z3cform.captionedrelationfield collective.z3cform.chosen collective.z3cform.datagridfield collective.z3cform.jsonwidget collective.z3cform.select2 dexterity.localroles dexterity.localrolesfield experimental.gracefulblobmissing fortytwo i18ndude iw.rejectanonymous keycloak-and-plone lineage.controlpanels lineage.themeselection mr.scripty mrs-developer pas.plugins.eea pas.plugins.headers pas.plugins.tfa plone_clean_history plone.app.locales plone6-autologin-extension ploneconf.site plonex Products.csvreplicata Products.DateRecurringIndex Products.LoginLockout Products.PasswordStrength Products.PDBDebugMode Products.PrintingMailHost Products.RefBiblioParser pyf-gui pyf.aggregator pytest-jsonschema robotsuite rss-provider seven-training-addon tech-event training_buildout tui-forms volto-blocks-widget volto-contents-next volto-csp volto-dropdownmenu volto-footer volto-form-block volto-form-counter volto-gdpr-privacy volto-google-analytics volto-hideshow-blocks volto-image-editor volto-middleware-binary volto-multilingual-widget volto-rss-receiver volto-secondarymenu volto-slimheader volto-social-settings volto-speakerdeck volto-subfooter volto-venue zestreleaser.towncrier zpretty