google/tsunami-security-scanner · error · ParameterException

Malformed GCS URL

Error message

Malformed GCS URL: '%s'

What it means

ScanResultsArchiver.Options.validate() throws a picocli ParameterException when --gcs-output-file-url is set but does not match the expected Google Cloud Storage URL regex (GS_URL_PATTERN, e.g. gs://bucket/path). It guards against mistyped output destinations before the scan results archiving step runs.

Solutions

  1. Use the canonical form gs://<bucket>/<object-path> for --gcs-output-file-url.
  2. Remove surrounding whitespace or stray characters from the flag value.
  3. If you want local output instead, drop the GCS flag and use the local output directory option.

Example fix

// before
--gcs-output-file-url=https://storage.googleapis.com/my-bucket/results.json
// after
--gcs-output-file-url=gs://my-bucket/results.json
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = gcsUrl != null && !gcsUrl.isBlank() && gcsUrl.matches("^gs://[^/]+/.+");

Try / catch

try { archiverOptions.validate(); } catch (ParameterException e) { System.err.println("Fix --gcs-output-file-url: " + e.getMessage()); }

Prevention

When it happens

Trigger: Passing --gcs-output-file-url with a value like 'https://storage.googleapis.com/...' or 'gs:/bucket/x' that does not fully match GS_URL_PATTERN, checked in validate() at ScanResultsArchiver.java:73.

Common situations: Using an HTTP URL to a GCS object instead of the gs:// URI scheme; missing the bucket; extra whitespace; typos like 'gcs://' or a single slash after the scheme.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of google/tsunami-security-scanner@363ba87b35 (2026-09-13). Data as JSON: /api/errors/4941e069e562839f. Report an issue: GitHub.

Appendix: source

Thrown at main/src/main/java/com/google/tsunami/main/cli/ScanResultsArchiver.java:73

        description = "The GCS file url for the uploaded scanning results.")
    public String gcsOutputFileUrl;

    @Parameter(
        names = "--scan-results-gcs-output-format",
        description = "The format of the scanning results uploaded to GCS bucket.")
    public OutputDataFormat gcsOutputFormat;

    @Parameter(
        names = "--scan-results-logging-enabled",
        description = "Enable logging of the scan results.",
        arity = 1)
    public Boolean loggingEnabled = false;

    @Override
    public void validate() {
      if (!Strings.isNullOrEmpty(gcsOutputFileUrl)
          && !GS_URL_PATTERN.matcher(gcsOutputFileUrl).matches()) {
        throw new ParameterException(String.format("Malformed GCS URL: '%s'", gcsOutputFileUrl));
      }
    }
  }

  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

  private final Options options;
  private final RawFileArchiver rawFileArchiver;
  private final GoogleCloudStorageArchiver.Factory googleCloudStorageArchiverFactory;

  @Inject
  // TODO(b/145315535): inject archivers using multibinder instead.
  ScanResultsArchiver(
      Options options,
      RawFileArchiver rawFileArchiver,
      GoogleCloudStorageArchiver.Factory googleCloudStorageArchiverFactory) {
    this.options = checkNotNull(options);
    this.rawFileArchiver = checkNotNull(rawFileArchiver);

View on GitHub (pinned to 363ba87b35)