Skip to content

[Actions] Parse multipart Content-Type structurally instead of using a prefix check #735

Description

@cssbruno

Priority

Medium — request parsing correctness and clearer generated runtime behavior.

Context

runtime/app/backend.go detects multipart action requests with:

contentType := strings.ToLower(strings.TrimSpace(request.Header.Get("Content-Type")))
return strings.HasPrefix(contentType, "multipart/form-data")

Generated multipart-capable actions then choose between ParseMultipartForm and ParseForm based on this helper.

Problem

A prefix check is not a media-type parser.

Consequences:

  1. Invalid media types such as multipart/form-dataevil can be routed into multipart parsing.
  2. Parameters are not parsed or validated structurally.
  3. The behavior can drift from Go's normal mime.ParseMediaType / request parsing expectations.
  4. Tests may accidentally pin permissive behavior that is not intended as part of the public contract.

The normal HTTP contract is that media types should be parsed as structured values, with parameters separated by semicolons.

Proposed direction

Use mime.ParseMediaType to classify multipart requests:

mediaType, _, err := mime.ParseMediaType(request.Header.Get("Content-Type"))
return err == nil && strings.EqualFold(mediaType, "multipart/form-data")

Malformed multipart content types should produce a deterministic bad-request path rather than being classified by a raw string prefix.

Acceptance criteria

  • Multipart detection uses mime.ParseMediaType or an equivalent structured parser.
  • Valid multipart/form-data; boundary=... requests still parse as multipart.
  • Invalid values such as multipart/form-dataevil are not treated as multipart.
  • Missing or malformed multipart boundaries produce deterministic HTTP 400 responses.
  • Tests cover uppercase/lowercase media type, valid parameters, invalid prefix-only media types, and ordinary URL-encoded forms.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions