google/tsunami-security-scanner · error · ValueError

Illegal header value

Error message

Illegal header value %s.

What it means

_canonicalize_header_name also validates the header value against _is_legal_header_value (analogous regex). Values containing illegal characters (e.g. newlines, control characters) raise ValueError('Illegal header value ...') to prevent header injection and malformed requests.

Solutions

  1. Inspect the value for control characters (repr() reveals \n, \r, \x00) and strip or reject them
  2. Collapse multi-line content: value.replace('\n', ' ').replace('\r', ' ') or split into separate headers
  3. Never interpolate raw user input into header values without sanitization
  4. Encode/quote the value if the header semantics allow it (e.g. base64 for binary data)

Example fix

// before
builder.add_header('X-Note', user_comment)  # may contain newlines
// after
builder.add_header('X-Note', user_comment.replace('\r', '').replace('\n', ' '))
Defensive patterns

Strategy: validation

Validate before calling

def is_safe_header_value(value):
    return isinstance(value, str) and not any(c in value for c in '\r\n\x00')

Try / catch

try:
    builder.add_header(name, value)
except ValueError:
    builder.add_header(name, sanitize(value))

Prevention

When it happens

Trigger: add_header('X-Foo', 'v1\nv2: injected') (CR/LF injection), a value with NUL or other control bytes, or a value read from a file/network that contains trailing control characters.

Common situations: Reflecting untrusted input into header values; reading tokens from files without stripping whitespace/newlines; template substitution injecting multi-line content into a header.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at plugin_server/py/common/net/http/http_headers.py:104

    Raises:
      ValueError: If name or value is None. If header name or value pair does
      not comply with standards.
    """
    if name is None:
      raise ValueError('Name cannot be None.')
    if value is None:
      raise ValueError('Value cannot be None.')
    if canonicalize:
      name = self._canonicalize_header_name(name, value)
    self.http_headers.raw_headers[name].append(value)
    return self

  def _canonicalize_header_name(self, name, value) -> str:
    if not self._is_legal_header_name(name):
      raise ValueError('Illegal header name %s.' % name)
    if not self._is_legal_header_value(value):
      raise ValueError('Illegal header value %s.' % value)
    return _canonicalize(name)

  def _is_legal_header_name(self, name: str) -> bool:
    return bool(re.fullmatch(self.HEADER_NAME_MATCHER, name))

  def _is_legal_header_value(self, value: str) -> bool:
    return bool(re.fullmatch(self.HEADER_VALUE_MATCHER, value))


def _canonicalize(header_name: str) -> str:
  """Normalize header field name.

  Args:
    header_name: An HTTP header field name.

  Returns:
    An HttpHeaderField value or the header_name in lowercase.
  """

View on GitHub (pinned to 363ba87b35)