Most security stories start with something broken. This one starts with everything working as designed.
Researchers at Reco have been tracking a campaign they call City-Forum, named after a domain registered in 2002, abandoned, and now resolving to a generic rented server from a German hosting provider. From that server, someone has been pulling records out of Salesforce and ServiceNow portals around the world.
The activity has not stopped, and there is more of it than there was. Every request Reco has seen from this address arrived as a guest. The targets they can see span telecom operators, banks and financial-services firms, enterprise-software vendors including security and data-privacy companies, and public-sector portals.
What passive DNS establishes is that the domain has resolved to this address since at least March 2025, so the infrastructure has been standing for a while. When the scanning started is a different question.
Here is the part worth sitting with: no software was exploited. No credentials were needed. There is no vulnerability here to patch. The attacker visited public customer portals as an anonymous visitor and asked them, politely and repeatedly, for their contents. The portals answered.
The guest in the room
Salesforce gives every Experience Cloud site its own standing account called the guest user, and every ServiceNow instance has one too. It is a real user with a profile and permissions like any other. When an unauthenticated stranger loads your support portal or your knowledge base, that is who they are browsing as. The guest user is not optional, it cannot be deleted, and it arrives with permissions that somebody, at some point, configured.
Nothing came out of these portals that they had not been configured to hand over.
Nitay Bachrach, Security Researcher at Reco, describes the underlying problem: “The core issue is that ‘what is public’ and ‘what should be public’ are two different things, and that’s exactly what the attacker exploited.”
Why this one stands out
Attackers have been abusing over-permissioned Salesforce guest users for a while, and there are off-the-shelf tools for it. This operator did not use them.
They built their own instead. Most of the resulting traffic still went down the well-trodden route: Salesforce’s older Aura framework, whose guest user has been a documented target for long enough that Reco has written up a previous campaign working the same way. That is where the bulk of this operator’s Salesforce effort landed. The busiest single target Reco observed logged over 560,000 events from this one address across the campaign window, almost all of it Aura enumeration.
What makes the campaign worth reading about is the rest of the toolkit, pointed at two places nobody had bothered to look. The first is the data layer behind Salesforce’s newer site framework, which the existing attack tools ignore entirely. Reco’s phrase for it is an offensive blind spot. The second is a ServiceNow portal search endpoint so undocumented that ServiceNow publishes no reference for it. Reco worked out how it behaves by reading the code behind the search box on a stock portal. Obscurity is not what makes it dangerous, though. The endpoint is public by design, and what it hands back depends entirely on how the sources behind it are configured.
One of the two most common sources that ship with the platform checks whether you are logged in before it goes near data. The other has no such check at all. It relies entirely on who has been granted read access to each knowledge base, which is a configuration question with nothing in the code to warn you either way.
The two behave nothing alike. On the Salesforce side the new work was thin next to the Aura flood, a few requests against each API version on each subsite it found, which is roughly what you would expect while Aura sites are still the more common target. On ServiceNow it was the opposite: once the tool found a portal, almost everything it did there went at that one search endpoint. Both halves show the same homework. They point to someone who sat down with these platforms, learned them properly, and went looking for doors no scanner was checking.
Who that someone is, Reco will not say. The activity resembles the ShinyHunters Experience Cloud campaign, guest enumeration of Salesforce over Aura and GraphQL, and Reco’s position is that a campaign not matching a group’s last known fingerprint tells you nothing on its own, since actors rewrite tooling and rent new boxes constantly. One thing is unlike those campaigns, offered as a soft signal rather than a finding: this operator has held a single address for at least seventeen months, with no rotation at any point.
The uncomfortable bit: you cannot see what left
Suppose you go looking and find this traffic in your own logs. You will learn less than you would like.
On ServiceNow, the transaction log records that a search happened and roughly how much came back, but not the search terms. Response size is the one thing there that speaks to what came back, and the last section below has what to do with it. Salesforce gives you more, though not enough to close the question. As Bachrach describes it, “Salesforce is somewhat better for what was attempted (which Aura actions, LWR GraphQL version-sweep URIs, self-reg probes). Event Monitoring doesn’t show which records/fields were returned.”
So the logs tell you what was tried, not what was taken. On the obvious follow-up, Bachrach says: “It is not possible to determine what was leaked based on the audit logs. An organization would need to simulate the requests internally and analyze the responses.”
In other words, to find out what an anonymous visitor could read, someone on your side has to go and be an anonymous visitor.
There is a catch in doing that, at least on ServiceNow. The portal search endpoint answers an anonymous request with the same HTTP 201 whether or not it has anything to hand over. A portal that is leaking and a portal that is shut look identical from the outside, and the only thing separating them is whether the body that comes back is empty. A probe that returns cleanly has told you nothing until you read what it returned. The operator faced the same ambiguity and turned it into a method, mapping each portal’s contents by noting which search terms produced a response with anything in it.
Bachrach’s position on when this crosses into something customers hear about: “If the data contains PII or other private data, customers should be notified.” The records were technically reachable by anyone. Whether they should have been is the part that determines the phone calls you make afterwards.
The same mistake, on both platforms
Asked which misconfiguration turns up most often, Bachrach points to one: “The most frequent misconfiguration was guest/anonymous over-permission. It was the root cause on both platforms.”
He also separates the highest-impact fix from the most common problem: “Salesforce guest sharing rules are the highest-impact fix, but not necessarily the most common misconfiguration.” Sharing rules are where the leverage is, so start there, but do not stop there and assume the job is done.
None of this is glamorous work, and on ServiceNow it is more than a permissions screen. But it is a finite job, and the server on the other end has been sitting there since at least March 2025.
You found the traffic. Now what?
Bachrach offers guidance for the first hour. First, confirm it is this pattern.
In Salesforce, check Event Monitoring AuraRequest and Sites entries with USER_TYPE = ‘Guest’, looking for high volumes of getItems and getConfigData, /webruntime/…/vNN.0/graphql version sweeps, and hits on /SiteRegister and /CommunitiesSelfReg.
In ServiceNow, check syslog_transaction for /api/now/sp/search requests made as guest. Then sort those rows by output length. An empty result set has a small and consistent size, so anything sitting well above it is a search that came back with records. Start there.
Then remediate. On Salesforce:
- Tighten guest sharing rules.
- Strip guest object and field permissions.
- Disable “Access Activities” and “API Enabled” on the guest user.
- Disable self-registration if it is not needed.
- Disable guest file access and member visibility.
- On LWR sites, disable “Allow guest users to access public APIs” if it is not required.
On ServiceNow:
- Map guest portals to their search sources, and those sources to their scripts.
- Review knowledge base “Can Read” user criteria for unconstrained “Any User” access.
- Review the enabled scripted search sources (sp_search_source) for the portal.
- Detach bad kb_uc_can_read_mtom links rather than editing shared criteria.

