Research

Fail-Open URL Inspection in Google Cloud Model Armor Enables a Padding Bypass

Google Cloud Model Armor's malicious URL filter inspects only the first 40 URLs in a prompt or response, and the API gives callers no signal when scanning was partial.

Bryce Johnson, CISSP, Senior Security Researcher at TrustOnCloud
Bryce Johnson, CISSP & Mouzma Rani
Security Research, TrustOnCloud
4 min read
Flowchart of Model Armor URL inspection: when an input contains more than 40 URLs, only the first 40 are scanned, so a malicious URL beyond position 40 is not inspected and the API still returns SUCCESS and NO_MATCH_FOUND.
tl;dr

Google Cloud Model Armor's malicious URL filter evaluates only the first 40 URLs in a prompt or response. URLs beyond that limit are not evaluated, and the API response does not indicate that scanning was partial.

This creates an integration risk: downstream systems may treat a successful NO_MATCH_FOUND response as evidence that all URLs were evaluated, when in reality only a prefix of the input was scanned. An attacker who controls URL ordering can exploit this behavior by placing benign URLs first and pushing a malicious URL beyond the inspection boundary.

How We Found It

While testing Model Armor as part of our threat modeling work, we noticed a statement in the documentation that claimed the service inspected up to 40 malicious URLs.

Original Model Armor documentation note reading: Model Armor scans only the first 40 malicious URLs found in prompts and responses.
Figure 1: The original Model Armor documentation note, which stated the service scans only the first 40 malicious URLs found in prompts and responses.

That wording immediately raised a question:

How can a system know a URL is malicious before inspecting it?

To validate the behavior, we built controlled test cases using combinations of benign URLs and Safe Browsing phishing test URLs.

Our testing showed that inspection is positional. Model Armor scans only the first 40 URLs in the input, regardless of whether they are benign or malicious.

Documented Behavior vs Runtime Behavior

AspectDocumented BehaviorRuntime Behavior
Inspection ScopeFirst 40 malicious URLsFirst 40 URLs total
URLs ExcludedURLs beyond the malicious URL limitAny URL beyond position 40
Signal to CallerImplied inspection according to documented logicNo warning or indication that URLs were skipped

Reproduction Input

Positional test input: 40 benign URLs followed by a Safe Browsing test URL Text
https://example.com/1
https://example.com/2
...
https://example.com/40

# Position 41
https://testsafebrowsing.appspot.com/s/phishing.html

When the Safe Browsing test URL appeared within the first 40 positions, it was detected. When moved beyond position 40, no detection occurred.

Proof of Concept

A reproducible proof-of-concept containing the test code and validation steps used during this research is available here:

The Fail-Open Problem

The issue is not the existence of a processing limit. Many security controls enforce limits. The issue is that Model Armor provides no indication when the limit is reached. In our testing, requests containing malicious URLs beyond the inspection boundary returned:

Model Armor response for input with a malicious URL beyond position 40 JSON
{
  "invocationResult": "SUCCESS",
  "filterMatchState": "NO_MATCH_FOUND"
}

The response does not indicate that:

  • Scanning stopped after the first 40 URLs
  • Additional URLs were skipped
  • Inspection was incomplete

This creates a fail-open condition for integrations that treat SUCCESS and NO_MATCH_FOUND as authoritative allow signals. In those designs, uninspected content may continue through the system as though it had been fully evaluated.

Padding Bypass

Because URL inspection is positional, an attacker who controls input ordering can use benign URLs as padding:

  1. Place 40 benign URLs at the beginning of the prompt or response.
  2. Place a malicious URL at position 41 or later.
  3. Rely on the integration to treat NO_MATCH_FOUND as a complete allow decision.

The malicious URL falls outside the inspection window and may evade inspection entirely.

Padding Bypass Attack Flow Showing the 40-URL Inspection Window Text
URLs 1-40   -> inspected
──────────── inspection boundary ────────────
URL 41+     -> not inspected
URL 41      -> malicious URL

This follows the same pattern as other padding bypasses, where benign content is used to push malicious content beyond a system's inspection boundary.

Flowchart of Model Armor URL inspection: when an input contains more than 40 URLs, only the first 40 are scanned, so a malicious URL beyond position 40 is not inspected and the API still returns SUCCESS and NO_MATCH_FOUND.
Figure 2: The padding bypass flow. URLs 1 through 40 are inspected; anything placed at position 41 or later, including a malicious URL, falls outside the inspection window and the API still returns SUCCESS and NO_MATCH_FOUND.

Responsible Disclosure

We reported the issue to Google Cloud through coordinated disclosure.

Timeline

  • March 11, 2026: Issue identified and shared internally
  • March 16, 2026: Case opened with Google Cloud
  • March 18, 2026: Issue acknowledged
  • March 20, 2026: Documentation updated
  • May 18, 2026: Feature request submitted for a truncation indicator

Following disclosure, Google updated the documentation to state that only the first 40 URLs are scanned. The original documentation stated that Model Armor inspected up to 40 malicious URLs. That wording implied the service would identify and evaluate malicious URLs regardless of their position in the input. The updated documentation makes a different claim entirely: Model Armor scans only the first 40 URLs encountered and ignores the rest.

Updated Model Armor documentation note reading: Model Armor scans only the first 40 URLs found in prompts and responses.
Figure 3: The updated documentation note, revised after disclosure, now stating that only the first 40 URLs are scanned.

However, the runtime behavior remains unchanged. URLs beyond the first 40 positions are not inspected, and the API still does not indicate that scanning was incomplete.

Google confirmed that this behavior is currently expected and recommended that integrations account for the limit themselves.

Mitigations

Google provided several recommendations for deployments that process large numbers of URLs:

  • Account for the 40-URL inspection limit when designing downstream trust decisions.
  • Count URLs before sending content to Model Armor.
  • Split large inputs into multiple requests to ensure all URLs are scanned.
  • Use application logging and monitoring to identify inputs that likely exceeded the inspection limit.

We also submitted a feature request asking Google to expose a truncation indicator similar to the findings_truncated field already used by other Model Armor filters.

The control becomes shared between Google and the integrator:

RiskDetection signalMitigation controlOwnerTrustOnCloud Control ID
Prefix-padding bypassURL count greater than 40 in inputChunk input into 40-URL or smaller requestsIntegration layerSecuritycenter.C84
Partial-scan fail-openNo findings_truncated field in responseLog URL counts; treat over-limit responses as untrustedIntegration layerSecuritycenter.C85
Attacker-controlled input orderingUser-supplied or model-generated URL listNormalize and reorder before submission; prioritize by source trustApplication layerSecuritycenter.C84
Single-control relianceModel Armor SUCCESS is treated as authoritativeLayer with independent URL screening; do not rely on Model Armor aloneArchitectureSecuritycenter.C84

Conclusion

The most significant finding is not that Model Armor scans only 40 URLs. The more important issue is that callers receive no indication when that limit is reached.

As a result, applications may treat partially scanned input as fully evaluated. Until a truncation indicator is available, integrations should assume that large URL sets may have been only partially inspected and design their trust decisions accordingly.

Bryce Johnson, CISSP
Senior Security Researcher, TrustOnCloud
Bryce is a Senior Security Researcher at TrustOnCloud, where he builds threat models and control libraries for cloud services across AWS, Azure, and Google Cloud.
Anonymous avatar
Mouzma Rani
Security Researcher, TrustOnCloud
Mouzma is a Security Researcher at TrustOnCloud who investigates cloud service behavior and authored the proof-of-concept for this finding.
See how this maps to your Model Armor controls
TrustOnCloud tracks controls like Securitycenter.C84 and C85 so your team can catch fail-open gaps before they reach production.