Dev.to Security 🔐 Cybersecurity 👁 0 📖 4 min read

The build server is the credential store, and it is answering on the internet

The build server is the credential store, and it is answering on the internet app="JetBrains TeamCity" returns 1,890 matches on ZoomEye. Restricted to TLS, app="JetBrains TeamCity" && service="ssl" returns 792. A raw p

The build server is the credential store, and it is answering on the internet

app="JetBrains TeamCity" returns 1,890 matches on ZoomEye. Restricted to TLS, app="JetBrains TeamCity" && service="ssl" returns 792. A raw port query for 8111, the TeamCity server default, returns 1,019,838, which is not a count of TeamCity servers at all.
All three were collected on 23 October 2026 through the ZoomEye API. The third number is the one to internalise before reading the other two: a port is a shared address space, and an unqualified port query measures everything that binds it.

Why the CI server belongs in an exposure review

A build server holds more privileged material than most production systems. It has deployment credentials for the environments it ships to, package registry tokens, signing keys, and often a service account with write access to the source repository it builds from.
That is not an argument for secrecy about the fact. It is the reason the reachability question deserves a deliberate answer: is the administrative interface of this system exposed to a network that does not need it, and does it require a credential that would survive a leak from elsewhere.
The TeamCity number is small compared with most figures in this series, and small numbers are a different kind of problem. A population of 1,890 identified hosts is small enough that a targeted list can be assembled from it, which changes the threat from opportunistic scanning to directed enumeration.

The Jenkins advisories that make this concrete

On 16 September 2026, Jenkins published advisories for a set of Script Security Plugin defects. CVE-2026-92122, CVE-2026-92123, CVE-2026-92124, CVE-2026-92125 and CVE-2026-92129 are each rated 8.8 or 7.5 and each describe a sandbox escape available to a user with permission to define and run sandboxed scripts, including Pipelines.
The mechanisms are varied and worth listing because they show how a sandbox fails at its boundaries rather than at its centre. The proxy created when a script coerces a value to an interface is not checked when the value inherits a method of the same name (92122). Operations on a null receiver are not intercepted (92123). A cast applied to a collection is checked on the collection rather than on the elements read from it (92124). The @GroovyASTTransformationClass annotation is not rejected, so an AST transformation runs at compile time (92125). Methods added to a class at runtime are not checked (92129).
Every one of them ends the same way: arbitrary code execution in the context of the Jenkins controller JVM.
The plugin version named in the advisories is 1415.v9a_f9b_3a_c253d and earlier. That is a precise, checkable string, and it is the most useful line in the advisory for an operator.

Small population, large consequence

The relevance to a TeamCity count is structural. Both products exist to execute code an authorised user supplies, on infrastructure that holds deployment credentials. A permission that allows a user to define a pipeline is, in practice, a permission that allows that user to run code on the controller if the sandbox has a gap.
That makes two questions meaningful for any CI server in an exposure inventory. Who can define a job, and what separates the job execution from the controller's own credentials.
For Jenkins specifically, the Script Security sandbox is the separation mechanism, and the September advisories show it leaking in five independent ways. An operator whose upgrade window is measured in weeks should know that the current plugin string is the version that matters, not the product version.

Verification steps that produce an answer

Read the plugin version directly. The Jenkins script console and the plugin manager both report installed versions, and the advisory string can be matched exactly. A pipeline that greps the plugin manager output into a report makes the check continuous rather than annual.
Check whether the administrative interface answers from outside the build network. For a TeamCity server, the /app/rest/server endpoint returns version information without authentication on default installations. A 200 response from a network that should not reach the server is the finding, independent of the CVE list.
Inventory the credentials the server holds. This is the step that converts an exposure finding into a risk statement. If the controller can deploy to production and push to the main branch, its exposure is a production risk, and the exposure review should escalate accordingly.
Restrict job definition rights. The advisories are rated 8.8 with PR:L because they require a low-privileged authenticated user. Reducing the population that holds that permission reduces the population that can reach a sandbox gap before the patch lands.

Retention questions after an incident

If a CI server is compromised, the reconstruction depends on records that are usually turned off. Build logs show what a job printed, not what the controller executed. Jenkins job configuration history, if the built-in audit trail is enabled, shows changes to job definitions. Agent console output is ephemeral by default.
The comparison worth making now is between what you retain and what an investigator would ask for in the first hour: which user created this pipeline, when did its definition change, and which credentials were read during the build.

References

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.