Back to Articles

Inside Google's Tsunami Security Scanner Plugins: The AI Infrastructure Security Arsenal You Haven't Heard About

[ View on GitHub ]

Inside Google’s Tsunami Security Scanner Plugins: The AI Infrastructure Security Arsenal You Haven’t Heard About

Hook

While security researchers obsess over Kubernetes CVEs, machine learning platforms like MLflow and Ray are running with default credentials in production, exposing training data, model weights, and API keys. Google’s Tsunami plugin collection addresses this blindspot with over 100 specialized detectors.

Context

Traditional vulnerability scanners excel at finding CVEs in web servers and network services, but they struggle with the new generation of infrastructure: machine learning platforms, workflow orchestrators, and data science tools that have become critical to modern tech stacks. When Google released Tsunami Security Scanner in 2020 as an extensible network scanning framework, they recognized that vulnerability detection couldn’t be one-size-fits-all. The tsunami-security-scanner-plugins repository emerged as the community catalog for this ecosystem, providing pre-built detectors that organizations could deploy without writing scanner logic from scratch.

What makes this repository particularly interesting is its focus on AI/ML infrastructure security—a domain that traditional security tools largely ignore. As companies rush to deploy LLMs, training pipelines, and inference servers, they’re often unaware that tools like Gradio, H2O, and PyTorch Serve ship with authentication disabled by default or have known RCE vulnerabilities. These aren’t theoretical risks: exposed MLflow instances have leaked proprietary model architectures, and misconfigured Ray clusters have provided attackers with arbitrary code execution on GPU-rich infrastructure. The Tsunami plugin repository provides detection capabilities specifically built for this modern attack surface.

Technical Insight

Plugin Types

TargetInfo + NetworkServices

Load & Initialize

Load & Initialize

DetectionReportList

DetectionReportList

DetectionReportList

Tsunami Core Scanner

Plugin Loader

Google Plugins

Community Plugins

Vuln Detectors

Credential Testers

Exposed UI Checkers

Scan Results

System architecture — auto-generated

The plugin architecture follows a classic provider pattern where each plugin implements the VulnDetector interface from the core Tsunami framework. Plugins receive a TargetInfo object containing network reconnaissance data and return a DetectionReportList describing any vulnerabilities found. The separation between the scanning engine and detection logic means you can add new vulnerability checks without modifying the core scanner.

Here’s the structure of a typical detector plugin for exposed Gradio instances:

@PluginInfo(
    type = PluginType.VULN_DETECTION,
    name = "GradioExposedUiDetector",
    version = "0.1",
    description = "Detects exposed Gradio ML application interfaces.",
    author = "Tsunami Team",
    bootstrapModule = GradioExposedUiDetectorBootstrapModule.class)
public final class GradioExposedUiDetector implements VulnDetector {

  private final HttpClient httpClient;

  @Inject
  GradioExposedUiDetector(@Tsunami HttpClient httpClient) {
    this.httpClient = httpClient;
  }

  @Override
  public DetectionReportList detect(
      TargetInfo targetInfo, ImmutableList<NetworkService> matchedServices) {
    return DetectionReportList.newBuilder()
        .addAllDetectionReports(
            matchedServices.stream()
                .filter(this::isWebService)
                .filter(this::isGradioRunning)
                .map(this::buildDetectionReport)
                .collect(toImmutableList()))
        .build();
  }

  private boolean isGradioRunning(NetworkService service) {
    String targetUri = buildTargetUrl(service);
    try {
      HttpResponse response = httpClient.send(
          get(targetUri).withEmptyHeaders().build());
      return response.status().isSuccess()
          && response.bodyString().get().contains("gradio_config");
    } catch (IOException e) {
      return false;
    }
  }
}

The plugin performs HTTP fingerprinting to identify Gradio instances by looking for framework-specific markers in the response. This pattern repeats across the repository: make minimal HTTP requests, check for identifying strings or behaviors, and report findings with severity levels. The framework handles all the network-level orchestration, retry logic, and report aggregation.

What’s architecturally interesting is the dual-tree structure: Google-maintained plugins live under google/detectors/ while community contributions go into community/detectors/. This separation allows Google to maintain quality standards for their officially-supported plugins while still fostering community growth. Each plugin is essentially a self-contained module with its own dependencies declared in a build.gradle file, built using the Bazel build system.

The AI/ML infrastructure focus becomes apparent when you examine the detector catalog. There are specialized plugins for Ray cluster RCE vulnerabilities (CVE-2023-48022), Jupyter Notebook authentication bypass, exposed MLflow tracking servers, and misconfigured Apache Airflow instances. These plugins understand the specific APIs and authentication patterns of ML platforms—knowledge that generic scanners lack. For instance, the MLflow detector knows to check both the /api/2.0/mlflow/experiments/list endpoint for API access and the web UI for authentication status.

The credential testing plugins take a different approach, implementing the PasswordCredentialTester interface to attempt authentication against services using common default credentials. This is particularly valuable for ML infrastructure where vendors often ship products with well-known default passwords that administrators forget to change. The plugin architecture allows these credential tests to run only after service detection, avoiding noisy failed authentication attempts against non-target services.

Dependency injection through Guice enables plugins to access shared resources like HTTP clients, DNS resolvers, and payload generators without tight coupling. This makes testing easier—you can inject mock HTTP clients to unit test detection logic without making real network calls. The @Tsunami qualifier annotation marks framework-provided dependencies, making it clear which components come from the core scanner versus plugin-local dependencies.

Gotcha

The most significant limitation is the hard dependency on the Tsunami Scanner core framework. These plugins are not standalone tools—you cannot run them independently or integrate them into other security scanning pipelines without significant refactoring. This creates a chicken-and-egg problem: the plugin repository is only valuable if you’ve already committed to Tsunami, but many security teams are hesitant to adopt Tsunami without seeing the available detection capabilities first. If your organization has standardized on a different scanning platform like Nuclei or Nessus, these plugins provide reference implementations at best, not drop-in functionality.

The Java implementation creates a barrier to entry for many security researchers who would otherwise contribute plugins. The modern security community gravitates toward Python or Go for tooling, and requiring Java knowledge, Gradle build configuration, and Guice dependency injection significantly narrows the contributor pool. You can see this reflected in the relatively slow pace of community contributions compared to YAML-based template repositories like nuclei-templates, which have thousands of community-contributed detectors. The build system uses Bazel, which adds another layer of complexity—expect to spend time wrestling with BUILD files and dependency declarations before you successfully compile your first plugin. Documentation within the repository is sparse; you’ll need to reference the main Tsunami documentation site and read existing plugin source code to understand patterns and best practices.

Verdict

Use if: You’re already running Tsunami Security Scanner in your security pipeline and need coverage for AI/ML infrastructure vulnerabilities that traditional scanners miss. The specialized detectors for MLflow, Ray, Gradio, and similar platforms provide real value that’s hard to find elsewhere. Also use this if you’re building security tooling for organizations heavily invested in data science infrastructure—the plugin source code serves as excellent reference implementations for detecting ML platform vulnerabilities, even if you’re targeting a different scanner. Skip if: You haven’t adopted Tsunami as your primary scanning framework, your security team lacks Java expertise, or you need general-purpose vulnerability detection rather than specialized ML platform coverage. The barrier to entry is too high if you’re just exploring options. Also skip if you need rapid iteration on new detectors—YAML-based template systems like Nuclei will get you to production detection faster. Consider this a specialized tool for organizations with specific AI/ML security requirements and existing Tsunami investments, not a general-purpose starting point for vulnerability scanning.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/ai-dev-tools/google-tsunami-security-scanner-plugins.svg)](https://starlog.is/api/badge-click/ai-dev-tools/google-tsunami-security-scanner-plugins)