{"record":{"id":"103b05b7b9b3948c","repo":"google/tsunami-security-scanner","slug":"illegal-header-name-s","errorCode":null,"errorMessage":"Illegal header name %s.","messagePattern":"Illegal header name (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"plugin_server/py/common/net/http/http_headers.py","lineNumber":102,"sourceCode":"    Returns:\n      The builder object.\n\n    Raises:\n      ValueError: If name or value is None. If header name or value pair does\n      not comply with standards.\n    \"\"\"\n    if name is None:\n      raise ValueError('Name cannot be None.')\n    if value is None:\n      raise ValueError('Value cannot be None.')\n    if canonicalize:\n      name = self._canonicalize_header_name(name, value)\n    self.http_headers.raw_headers[name].append(value)\n    return self\n\n  def _canonicalize_header_name(self, name, value) -> str:\n    if not self._is_legal_header_name(name):\n      raise ValueError('Illegal header name %s.' % name)\n    if not self._is_legal_header_value(value):\n      raise ValueError('Illegal header value %s.' % value)\n    return _canonicalize(name)\n\n  def _is_legal_header_name(self, name: str) -> bool:\n    return bool(re.fullmatch(self.HEADER_NAME_MATCHER, name))\n\n  def _is_legal_header_value(self, value: str) -> bool:\n    return bool(re.fullmatch(self.HEADER_VALUE_MATCHER, value))\n\n\ndef _canonicalize(header_name: str) -> str:\n  \"\"\"Normalize header field name.\n\n  Args:\n    header_name: An HTTP header field name.\n\n  Returns:","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/google/tsunami-security-scanner/blob/363ba87b3543f8ae8e4304d3416818f03da7f262/plugin_server/py/common/net/http/http_headers.py#L84-L120","documentation":"When canonicalize is enabled, add_header validates the header name against HEADER_NAME_MATCHER (a regex over legal RFC-style token characters). If the name contains characters outside that set, ValueError('Illegal header name ...') is raised before any header is stored.","triggerScenarios":"add_header('X Foo', 'v') (space), add_header('X-Foo:', 'v') (colon), or a name built by string concatenation that includes a newline, non-ASCII characters, or punctuation not allowed in header tokens.","commonSituations":"Building header names dynamically from user input or data-driven configs; typos like 'Content Type'; accidentally passing 'Name: value' as a single name string (common when copying curl headers).","solutions":["Print the offending name and check it against legal token characters (alphanumerics plus typical token punctuation like - _ .)","Split any 'Name: value' string into separate name and value arguments","Sanitize or reject header names from untrusted sources before calling add_header","Pass canonicalize=False only if you are certain the name is already canonical"],"exampleFix":"// before\nbuilder.add_header(name_from_input, 'v')  # may contain ' ' or ':'\n// after\nimport re\nif re.fullmatch(r'[A-Za-z0-9-]+', name_from_input):\n  builder.add_header(name_from_input, 'v')","handlingStrategy":"validation","validationCode":"import re\nLEGAL_NAME = re.compile(r'^[A-Za-z0-9-]+$')\ndef can_add(name):\n    return bool(LEGAL_NAME.fullmatch(name))","typeGuard":null,"tryCatchPattern":"try:\n    builder.add_header(name, value)\nexcept ValueError as e:\n    logging.warning('Rejected header %r: %s', name, e)","preventionTips":["Split 'Name: value' strings before passing them to add_header","Whitelist allowed header names when sourced from user input","Never build header names by concatenating arbitrary strings"],"tags":["python","http","headers","validation"],"backgroundTag":"invalid-argument-format","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"}