Production deployment WAF (Cloud Armor) silently blocking valid image uploads — bodies never reach the app

Summary: Starting around early June 2026, a portion of image uploads to my deployed app (picAid.app) began hanging at 0% in production only. The same uploads work perfectly in the dev preview. After extensive tracing, the cause is the production deployment’s front-end proxy / WAF layer (appears to be Google Cloud Armor) inspecting and blocking the request body before it ever reaches my Express server.

Key symptoms:

  • Affected uploads never reach my app — there is zero server-side log output for them (a successful upload logs normally; a blocked one logs nothing at all). So the block is happening upstream of my container.
  • 100% reproducible per-file: a given image either always fails or always succeeds.
  • Dev preview never reproduces it — only the deployed/published environment does, which points at an infrastructure layer that only exists in production.
  • The connection appears to stall/hang rather than return a clean 4xx, so the client just sits at 0%.

What I proved about the trigger:

  1. Some failures were caused by JPEGs carrying large text/XML metadata (Adobe XMP packets, Photoshop/IPTC APP13, bulky EXIF). Losslessly stripping that metadata client-side fixed those files.
  2. But other failures had clean metadata and still got blocked. I compared a blocked file against a successfully-uploaded file and found the successful file actually contained more attack-looking byte sequences in its raw compressed image data (e.g. ../, ..\, http://) than the blocked one. This strongly suggests a WAF signature/libinjection rule is matching against raw binary image bytes, which is effectively non-deterministic for legitimate image content.

Why this is a platform issue: Image/binary uploads are normal traffic. A WAF rule that inspects raw multipart binary bodies and matches SQL/path-traversal/XSS signatures against compressed image bytes will block arbitrary valid images with no way for the developer to “clean” the file. It also fails silently (stalls with no 4xx and no log), which makes it very hard to diagnose. This behavior appears to have changed recently — these uploads worked before.

My workaround (in case it helps others): I base64-encode the upload body and decode it server-side. Base64’s alphabet contains none of the characters WAF signature rules look for, so the rules no longer match. I also strip JPEG metadata client-side. Both are client+server changes — not something most users would expect to need.

Ask: Please check whether a recent Cloud Armor / deployment-proxy WAF ruleset change is now inspecting and blocking binary upload bodies, and consider (a) exempting multipart/form-data binary bodies from text-signature rules, and (b) returning a proper error response instead of silently stalling the connection so developers can at least detect it.