{"record":{"id":"5caa2366335b3f65","repo":"google/tsunami-security-scanner","slug":"a-request-body-is-not-allowed-for-http-get-head-request","errorCode":null,"errorMessage":"A request body is not allowed for HTTP GET/HEAD request.","messagePattern":"A request body is not allowed for HTTP GET/HEAD request\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"plugin_server/py/common/net/http/http_request.py","lineNumber":108,"sourceCode":"    return self\n\n  def set_request_body(self, request_body: Optional[bytes] = None) -> 'Builder':\n    \"\"\"Set the request body.\"\"\"\n    self.http_request.body = request_body\n    return self\n\n  def with_empty_headers(self) -> 'Builder':\n    \"\"\"Set an empty Http_headers for the request.\"\"\"\n    self.set_headers(HttpHeadersBuilder().build())\n    return self\n\n  def build(self) -> 'HttpRequest':\n    if (\n        self.http_request.method == HttpMethod.GET\n        or self.http_request.method == HttpMethod.HEAD\n    ):\n      if self.http_request.body:\n        raise ValueError(\n            'A request body is not allowed for HTTP GET/HEAD request.')\n    return self.http_request\n","sourceCodeStart":90,"sourceCodeEnd":111,"githubUrl":"https://github.com/google/tsunami-security-scanner/blob/363ba87b3543f8ae8e4304d3416818f03da7f262/plugin_server/py/common/net/http/http_request.py#L90-L111","documentation":"HttpRequest.Builder.build() enforces that GET and HEAD requests carry no body, per the HTTP specification. If a body was set on a GET/HEAD builder, ValueError is raised at build time rather than producing a request that servers would reject or misinterpret.","triggerScenarios":"Calling set_body(...) (or equivalent) on a builder whose method is GET or HEAD, then calling build(); commonly the method defaults to GET and body-setting code runs unconditionally.","commonSituations":"Code that always attaches a POST-style JSON body but the method was changed/derived to GET; passing query parameters as a body instead of the URL query string; shared request-building helpers that ignore the method.","solutions":["Change the HTTP method to POST/PUT/PATCH if a body is genuinely required","Move the data into the URL query string for GET requests (params, not body)","Skip body assignment when method is GET/HEAD","Reorder builder calls so the method is set first and gate body-setting on it"],"exampleFix":"// before\nbuilder.set_method(HttpMethod.GET).set_body(data)\nreturn builder.build()  # raises\n// after\nif data:\n  builder.set_method(HttpMethod.POST).set_body(data)\nelse:\n  builder.set_method(HttpMethod.GET)\nreturn builder.build()","handlingStrategy":"validation","validationCode":"def build_safe(builder, method, body=None):\n    if method in (HttpMethod.GET, HttpMethod.HEAD):\n        body = None\n    if body:\n        builder.set_body(body)\n    builder.set_method(method)\n    return builder.build()","typeGuard":null,"tryCatchPattern":"try:\n    return builder.build()\nexcept ValueError as e:\n    if 'GET/HEAD' in str(e):\n        logging.error('Body set on %s request', builder.http_request.method)\n    raise","preventionTips":["Set the HTTP method first, then conditionally set the body","For GET requests put data in the query string, not the body","Centralize request building in one helper that enforces method/body rules"],"tags":["python","http","request-validation"],"backgroundTag":"invalid-state-transition","analyzedSha":"363ba87b3543f8ae8e4304d3416818f03da7f262","analyzedAt":"2026-09-13T01:50:53.990Z","contentChangedAt":"2026-09-13T01:50:53.990Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}