cpan CGI 5.00

latest releases: 5.02, 5.01
6 hours ago

[ RELEASE NOTES ]

  • this is a security release fixing a large number of vulnerabilities,
    several of them exploitable by any client against any script. all
    users should upgrade
  • to fix them some default behaviour has changed, see BREAKING CHANGES
    below - most changes only affect malicious or malformed requests, but
    please read them before upgrading. where a change could reasonably
    affect a legitimate application an opt out or migration path is given
  • the minimum supported perl version is now 5.10

[ SECURITY ]

  • denial of service:
    • CVE-2026-120631: CGI::Cookie->parse (and so CGI->cookie) used a
      client supplied cookie expires value as a regex, so a Cookie header
      could make it die or backtrack catastrophically
    • CVE-2026-120632: a crafted multipart/related Content-Type header
      caused cubic regex backtracking (~15s of CPU for an 8KB header, no
      body needed)
    • CVE-2026-120650: request size, param and upload limits were missing
      or unenforced: $POST_MAX defaulted to no limit, and was not enforced
      at all for multipart bodies without a CONTENT_LENGTH (chunked
      encoding), or for the boundary line of a multipart body without a
      boundary=; PUTDATA/POSTDATA/PATCHDATA bodies were read into memory
      in one go; and there was no limit on the number of params or
      uploads in a request (a 40MB form body took 9s and 1.5GB of memory
      to parse) - see the new $CGI::MAX_PARAMS and $CGI::MAX_UPLOADS
    • CVE-2026-120651: an infinite loop reading a short PUT/POST/PATCH
      body when $DISABLE_UPLOADS was set
    • CVE-2026-120645: scrolling_list used submitted values as a regex
      for optgroups
    • CVE-2026-120646: uploadInfo() dereferenced plain strings as symbolic
      references, so died when given some, e.g. "0"
  • header injection / response splitting:
    • CVE-2026-120639: with autoEscape off, header() decoded HTML entities
      in extra header values after checking them for newlines, so

became CRLF; and multipart_start() and

CGI::Push::do_push did no newline checks
  • CVE-2026-120644: CGI::Cookie path/domain/expires were not checked,
    so ";" injected other cookie attributes
  • CVE-2026-120647: the header() -attachment filename did not escape
    quotes
  • open redirects, and URLs/forms pointing at other hosts:
    • CVE-2026-120633: url(), self_url(), virtual_host(), virtual_port()
      trusted the client supplied X-Forwarded-Host header, and an
      unvalidated Host, affecting the default redirect() location,
      start_html(-base=>1) and default start_form() actions
    • CVE-2026-120638: redirect() HTML decoded its URL after the
      application had checked it, e.g. "//evil.example/" became
      "//evil.example/"
    • CVE-2026-120636: URLs built from the client supplied REQUEST_URI
      could be protocol relative (//evil.example), absolute-form
      (http://evil.example/) or have backslashes, and url(-relative=>1)
      could return e.g. javascript:alert(1)
  • cross site scripting:
    • CVE-2026-120643: url()/self_url() could contain a raw single quote
      (URI->canonical decodes %27)
    • CVE-2026-120648: comment() text could end the HTML comment
  • information disclosure:
    • CVE-2026-120634: CGI::Carp warnings buffered for warningsToBrowser
      were not reset between requests in persistent environments, so one
      user's warnings could be shown to another
  • CVE-2026-120635: multipart parsing differentials (fields smuggled past
    a filtering proxy or WAF that parses per the RFCs):
    • the boundary was matched anywhere, not only at the start of a line
    • the boundary was used without its "--" for some User-Agents
    • Content-Disposition name/filename were found inside other
      parameters' quoted values
    • boundaries over the RFC 2046 limit corrupted and merged parts
  • other:
    • CVE-2026-120641: client supplied upload filenames could contain a
      path, allowing path traversal in applications that use them to save
      the file
    • CVE-2026-120640: clients could set POSTDATA/PUTDATA/PATCHDATA/
      XForms:Model through the query string or a form field,
      indistinguishable from the real body (e.g. a cross site HTML form
      posting to a JSON endpoint)
    • CVE-2026-120642: under taint mode the upload filename, uploadInfo()
      values, path_info, Accept(), and some cookie and url_param values
      were untainted
    • CVE-2026-120637: an unrecognised REQUEST_METHOD (e.g. OPTIONS) made
      the process' own command line arguments the request params

[ BREAKING CHANGES ]

  • X-Forwarded-Host is no longer used by url()/self_url()/virtual_host()
    /virtual_port(), and Host is only used if it is a valid host[:port].
    behind a reverse proxy pass the right Host / SERVER_NAME, or set
    $CGI::TRUST_X_FORWARDED_HOST = 1
  • $CGI::POST_MAX now defaults to 128MB, set it to -1 for no limit
  • $CGI::MAX_PARAMS (10,000) and $CGI::MAX_UPLOADS (1,000) are new
    limits, set them to -1 for no limit. requests exceeding any of the
    limits get a "413 Request entity too large" cgi_error
  • upload filenames (param('upload'), the upload filehandle, and the
    upload_hook) have any directory part and control characters removed.
    the raw value is in uploadInfo($fh)->{'Content-Disposition'}, or set
    $CGI::SANITIZE_UPLOAD_FILENAMES = 0
  • redirect() URLs and header() values are no longer HTML unescaped -
    pass e.g. /x?a=1&b=2, not /x?a=1&b=2
  • multipart_start() header names are now capitalised like header()'s
  • url(-relative=>1) prefixes a result that looks like it has a scheme
    with ./, and URLs built from REQUEST_URI are reduced to a path on
    this host (request_uri() still returns the literal value)
  • url()/self_url() percent encode single quotes
  • CGI::Cookie dies if path, expires or domain contain ";" or control
    characters, or domain isn't a valid host name
  • header() -attachment backslash escapes " and \ in the filename
  • comment() inserts a space into any "--" in its text
  • client sent params named POSTDATA, PUTDATA, PATCHDATA or XForms:Model
    are ignored (an application's own initializer can still set them)
  • under taint mode more request data is tainted, as listed above, so
    must be untainted before use in e.g. open() or system()
  • malformed multipart bodies are rejected: boundaries over 200
    characters, a body supplied boundary not starting with --, or a
    boundary line over 1KB. multipart/related requires the media type to
    be exactly multipart/related (its parameters may now be in any order)
  • offline (command line) debugging mode is only used when there is no
    REQUEST_METHOD and no CGI server, FastCGI or mod_perl
  • PUTDATA/POSTDATA/PATCHDATA upload_hook callbacks are now called per
    4K chunk, as they already were for multipart uploads
  • the IE 3.01 for Mac / DreamPassport multipart special case is removed

[ FIX ]

  • chunked (no CONTENT_LENGTH) multipart requests without a boundary=
    always failed, and the boundary line read now works under mod_perl
  • read_postdata_putdata ignored SPIN_LOOP_MAX, dying on the first zero
    length read
  • a second CGI->new in the same request lost cgi_error, and shared the
    first object's param arrays
  • optgroup() ignored the documented -novals option
  • import_names() wiped nested packages when clearing the namespace
  • an upload whose filename was "0" lost its name
  • an empty extra header() value came out as a lone "

[ META ]

  • minimum perl version is now 5.10
  • all modules are now version 5.00, including CGI::Cookie (was 4.59)

[ TESTING ]

  • tests for all of the above

Don't miss a new CGI release

NewReleases is sending notifications on new releases.