Security firm Reco has published research on a campaign it calls City Forum, after a domain tied to the single IP address behind it — 158.220.87.79, hosted on the German VPS provider Contabo.

Passive DNS puts that domain on that address since at least March 2025, with no migration since. Reco has not attributed the activity to a named group.

What it is doing

Reading customer portals. Methodically, for over a year.

The targets span telecoms, banking and financial services, enterprise software vendors — including security and data-privacy companies — and public sector bodies. Reco has not named individual organisations. At one target, the platform logged more than 560,000 events from that single address.

There is no exploit here

This is the part that makes it worth reading, and the part that makes it hard to fix.

Both Salesforce and ServiceNow let you publish a site that unauthenticated visitors can use — a support portal, a knowledge base, a case tracker. Both do it by giving anonymous visitors a guest user identity with a permission set. The attacker is not defeating that model. It is using it, exactly as configured, and reading everything the guest profile was granted.

Reco's own summary of the root cause is the sentence to keep: a guest identity granted more access than the site actually needed in order to serve the public.

How the requests look

The tooling is a compiled Go program, identifiable because it never changed the default Go net/http user agent — an operator hygiene failure of the same kind as a static API key left across a whole malware campaign, and just as useful to a defender.

On Salesforce it worked through both the older Aura framework and the newer Lightning Web Runtime sites via the UI-API, and it walked API versions v56.0 through v66.0 in sequence — trying each one in turn, because an object locked down in a recent version is sometimes still reachable through an older one. That is a deliberate technique, not scanning noise.

On ServiceNow it went at the Service Portal search endpoint, POST /api/now/sp/search, which is barely documented publicly. Somebody read the platform rather than a tutorial.

Why a year passed

Because none of it is an attack, in the sense that anything would alert on.

Every request is a well-formed, authorised query from a visitor the site was built to serve. There is no failed login, no injection string, no malformed input. The only signals available are volume and shape — one address, over a long period, sequentially enumerating API versions — and those live in platform event logs that most organisations never look at, if they have them enabled at all.

The parallel is the Entra directory records offered for sale last week, where the underlying complaint was also that ordinary authenticated users could enumerate far more of the directory than anyone intended. Same failure, different tenant setting.

What to do

If you run a public Salesforce or ServiceNow site, these are concrete and doable this week.

  • Audit the guest user profile itself. List every object and field it can read, then ask what the public page actually renders. Everything else is a finding.
  • Assume old API versions are in scope. The v56-to-v66 walk exists because sharing rules are not always enforced identically across versions. Testing your protections on the current version only is testing the wrong thing.
  • Look at your platform event logs for one address doing a lot. Salesforce Event Monitoring and ServiceNow's request logs both hold this. 560,000 events from a single IP is not subtle if anybody is looking.
  • Watch for default library user agents. Go net/http, python-requests and curl have no business driving a customer portal at volume.
  • Rate-limit the search endpoints, particularly ServiceNow's Service Portal search, which is designed to return matches across content.

What is not established

  • Who is behind it. Reco explicitly does not attribute.
  • Which organisations were scraped. None have been named.
  • What was taken in total. Reco reports the technique and the traffic, not an inventory.
  • Whether the data has been sold or used. No listing has been tied to this campaign.
  • Whether it has stopped. Reco reports the infrastructure as still active, with traffic climbing.