Version in base suite: 0.40068-2 Base version: libhtml-formhandler-perl_0.40068-2 Target version: libhtml-formhandler-perl_0.40068-3~deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libh/libhtml-formhandler-perl/libhtml-formhandler-perl_0.40068-2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libh/libhtml-formhandler-perl/libhtml-formhandler-perl_0.40068-3~deb13u1.dsc changelog | 14 ++ patches/CVE-2022-4993-r2.patch | 210 +++++++++++++++++++++++++++++++++++++++++ patches/series | 1 3 files changed, 225 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp3h975c0c/libhtml-formhandler-perl_0.40068-2.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp3h975c0c/libhtml-formhandler-perl_0.40068-3~deb13u1.dsc: no acceptable signature found diff -Nru libhtml-formhandler-perl-0.40068/debian/changelog libhtml-formhandler-perl-0.40068/debian/changelog --- libhtml-formhandler-perl-0.40068/debian/changelog 2022-03-25 16:32:07.000000000 +0000 +++ libhtml-formhandler-perl-0.40068/debian/changelog 2026-09-05 14:25:23.000000000 +0000 @@ -1,3 +1,17 @@ +libhtml-formhandler-perl (0.40068-3~deb13u1) trixie; urgency=medium + + * Rebuild for trixie + + -- Salvatore Bonaccorso Sat, 05 Sep 2026 16:25:23 +0200 + +libhtml-formhandler-perl (0.40068-3) unstable; urgency=medium + + * Team upload. + * HTML::FormHandler: stop routing foreign text into the Locale::Maketext + format (CVE-2022-4993) + + -- Salvatore Bonaccorso Fri, 14 Aug 2026 06:00:11 +0200 + libhtml-formhandler-perl (0.40068-2) unstable; urgency=medium [ Damyan Ivanov ] diff -Nru libhtml-formhandler-perl-0.40068/debian/patches/CVE-2022-4993-r2.patch libhtml-formhandler-perl-0.40068/debian/patches/CVE-2022-4993-r2.patch --- libhtml-formhandler-perl-0.40068/debian/patches/CVE-2022-4993-r2.patch 1970-01-01 00:00:00.000000000 +0000 +++ libhtml-formhandler-perl-0.40068/debian/patches/CVE-2022-4993-r2.patch 2026-09-05 14:25:23.000000000 +0000 @@ -0,0 +1,210 @@ +From: CPANSec Security Scanner Bot +Subject: [PATCH] HTML::FormHandler: stop routing foreign text into the Locale::Maketext format + +The first argument to add_error is the Locale::Maketext FORMAT: bracket groups +in it are compiled into method-dispatch code. Three kinds of text that +FormHandler did not author reach that position, all of them carrying submitted +request data: + + * _apply_actions traps warnings into $error_message (Validate.pm, the + $SIG{__WARN__} handler). A warning survives a SUCCESSFUL action, so an + ordinary numeric transform on a text field turns + `Argument "[sprintf,%2000000000d,0]" isn't numeric` into the format -- + Perl quotes the value verbatim, so the group is well formed and reaches + CORE::sprintf with an attacker-chosen width (~GB allocation). + * a type constraint's failure message. Moose renders the rejected value with + Devel::PartialDump when it can load it, Type::Tiny always uses its own + dumper, and both render a reference in bracket-and-comma form -- so on any + field with `apply => [ Str ]`, two same-named request parameters put + `[ "a", "b" ]` in the format and maketext croaks, which add_error re-dies: + an unhandled 500 with no payload at all. + * exceptions from a coercion or transform. + * a date parser's error message. Field/Date.pm passes + `$strp->errmsg || $@` -- DateTime::Format::Strptime's own text -- straight + into the format position. DTFS 1.80 answers a rejected value with the + fixed string "Your datetime does not match your pattern.", so there is no + reachable payload through it today; that is a property of the current + version of a separate distribution rather than of this code, and the + `|| $@` fallback is a second channel that was not exercised. Escaped for + the same reason as the others. + +Escape the bracket-notation metacharacters in all four before they are used +as a format. Tilde is Locale::Maketext's escape, and text with no brackets is +returned unchanged, so lexicon lookups and translated type-constraint messages +are byte-identical to before. + +Also: add_error derefs an arrayref first argument into (template, @args). That +spelling is the same list-or-arrayref convenience idiom as add_element_class +and friends; it is not documented for add_error, and an instrumented run of the +distribution's own suite (150 files, 1491 tests) never reaches the branch. What +does reach it is request data -- `$field->add_error($field->value)` where the +request parser folded a duplicate parameter into an arrayref puts submitted +text in element 0. Since no message the library raises arrives in that shape, +treat an arrayref argument as a value: keep the deref, render element 0 +literally. A caller who wants a compiled template passes it as a plain list, +`$field->add_error($template, @args)`, which is the documented spelling and is +unchanged. + +One case cannot be fixed here: an application that concatenates the value into +its own message, `add_error("The value '" . $field->value . "' is not +allowed")`, is indistinguishable from a legitimate template, so the add_error +POD now documents the hazard and the inert-argument idiom. + +Behaviour trade-offs -- the only output changes outside the attack cases: + + * a custom type constraint whose own message block uses bracket notation + (message { 'Try [quant,1,thing]' }) now renders that literally. Such a + block receives the rejected value and can interpolate it, so escaping it + is the safe default; a maintainer who would rather keep those compiled can + exempt the has_message branch specifically. + * an application calling the undocumented arrayref spelling with a template + that uses bracket notation, add_error([ 'Try [quant,_1,thing]', 3 ]), now + renders it literally; the list spelling of the same call still compiles. + +FormHandler's own message templates, and application templates passed to +add_error together with their arguments, are unaffected. + +Verified against the 0.40068 test suite: 150 files, 1491 tests, PASS both +before and after. A before/after table of rendered error messages +(maxlength, minlength, required, invalid select value, integer range, +duplicate-parameter arrays, application template with arguments, plain and +bracketed type messages, plain and bracketed warnings and exceptions) is +byte-identical except the lines above. + +--- a/lib/HTML/FormHandler/Validate.pm ++++ b/lib/HTML/FormHandler/Validate.pm +@@ -158,13 +158,40 @@ + $self->add_action(@apply_list); + } + ++# Locale::Maketext treats its FORMAT argument as bracket-notation source: any ++# '[...]' group inside it is compiled into method-dispatch code (see _compile ++# in Locale::Maketext). Messages FormHandler itself authors are templates on ++# purpose, but three kinds of text reaching _apply_actions are not ours and do ++# embed request data: ++# ++# * warnings trapped by the $SIG{__WARN__} handler in _apply_actions -- Perl ++# quotes the offending value into them verbatim, so a submitted value like ++# '[sprintf,%2000000000d,0]' arrives as a well-formed bracket group; ++# * a type constraint's failure message -- the type system renders a rejected ++# reference in bracket-and-comma form (Devel::PartialDump when Moose can ++# load it, Type::Tiny's own dumper always), so a duplicate request ++# parameter is enough to put '[ "a", "b" ]' into the format; ++# * exceptions from a coercion or a transform. ++# ++# Render those literally instead. Tilde is Locale::Maketext's escape character; ++# text containing no brackets comes back unchanged, so lexicon lookups and ++# translated type-constraint messages behave exactly as before. ++sub _escape_bracket_notation { ++ my ( $self, $text ) = @_; ++ ++ return $text if !defined $text || ref $text; ++ $text =~ s/~/~~/g; ++ $text =~ s/([\[\]])/~$1/g; ++ return $text; ++} ++ + sub _apply_actions { + my $self = shift; + + my $error_message; + local $SIG{__WARN__} = sub { + my $error = shift; +- $error_message = $error; ++ $error_message = $self->_escape_bracket_notation($error); + return 1; + }; + +@@ -199,10 +226,11 @@ + eval { $new_value = $tobj->coerce($value) }; + if ($@) { + if ( $tobj->has_message ) { +- $error_message = $tobj->message->($value); ++ $error_message = $self->_escape_bracket_notation( ++ $tobj->message->($value) ); + } + else { +- $error_message = $@; ++ $error_message = $self->_escape_bracket_notation($@); + } + } + else { +@@ -210,7 +238,8 @@ + } + + } +- $error_message ||= $tobj->validate($new_value); ++ $error_message ||= $self->_escape_bracket_notation( ++ $tobj->validate($new_value) ); + } + # now maybe: http://search.cpan.org/~rgarcia/perl-5.10.0/pod/perlsyn.pod#Smart_matching_in_detail + # actions in a hashref +@@ -235,7 +264,8 @@ + $action->{transform}->($value, $self); + }; + if ($@) { +- $error_message = $@ || $self->get_message('error_occurred'); ++ $error_message = $self->_escape_bracket_notation($@) ++ || $self->get_message('error_occurred'); + } + else { + $self->_set_value($new_value); +--- a/lib/HTML/FormHandler/Field.pm ++++ b/lib/HTML/FormHandler/Field.pm +@@ -864,7 +864,21 @@ + unless ( defined $message[0] ) { + @message = ( $class_messages->{field_invalid}); + } +- @message = @{$message[0]} if ref $message[0] eq 'ARRAY'; ++ if ( ref $message[0] eq 'ARRAY' ) { ++ # An arrayref argument is a value, not a message specification. The ++ # list-or-arrayref spelling here is the same convenience idiom as ++ # add_element_class and friends, it is not documented for add_error, ++ # and nothing in the distribution reaches it -- but request data does: ++ # $field->add_error($field->value), where the request parser folded a ++ # duplicate parameter into an arrayref, puts submitted text in element ++ # 0, which _localize hands to Locale::Maketext as bracket-notation ++ # source. Dereference as before, but render element 0 literally. ++ # A caller who really wants a compiled template passes it as a plain ++ # list: $field->add_error($template, @args). ++ my @args = @{ $message[0] }; ++ $args[0] = $self->_escape_bracket_notation( $args[0] ); ++ @message = @args; ++ } + my $out; + try { + $out = $self->_localize(@message); +@@ -1198,6 +1212,18 @@ + + return $field->add_error( 'bad data' ) if $bad; + ++The first argument is the localization FORMAT, which for a ++L handle means bracket notation in it is compiled and ++executed. Do not build that argument out of submitted data: a value ++containing a C<[...]> group would be run as a method call rather than ++shown. Pass the value as an argument instead, where it is inert: ++ ++ # wrong -- the submitted value becomes part of the format ++ $field->add_error( "The value '" . $field->value . "' is not allowed" ); ++ ++ # right -- the format is yours, the value is just an argument ++ $field->add_error( "The value '[_1]' is not allowed", $field->value ); ++ + =item error_fields + + Compound fields will have an array of errors from the subfields. +--- a/lib/HTML/FormHandler/Field/Date.pm ++++ b/lib/HTML/FormHandler/Field/Date.pm +@@ -66,7 +66,11 @@ + + my $dt = eval { $strp->parse_datetime( $self->value ) }; + unless ($dt) { +- $self->add_error( $strp->errmsg || $@ ); ++ # The parser's message is not ours to hand to the localizer as a ++ # bracket-notation FORMAT. DateTime::Format::Strptime 1.80 does not ++ # quote the rejected input into errmsg, but that is the parser's text ++ # to change, and the `|| $@` fallback is a second channel. ++ $self->add_error( $self->_escape_bracket_notation( $strp->errmsg || $@ ) ); + return; + } + $self->_set_value($dt); diff -Nru libhtml-formhandler-perl-0.40068/debian/patches/series libhtml-formhandler-perl-0.40068/debian/patches/series --- libhtml-formhandler-perl-0.40068/debian/patches/series 2022-03-25 16:32:07.000000000 +0000 +++ libhtml-formhandler-perl-0.40068/debian/patches/series 2026-09-05 14:25:23.000000000 +0000 @@ -1,2 +1,3 @@ whatis.patch whatis-Field-Role-RequestToken.patch +CVE-2022-4993-r2.patch