Skip to content

CVE-2026-19873 Repeatable counter_name takes an unbounded repeat count straight from the query string (CPU/memory DoS) #71

Description

@robrwo

Note: the description below was machine-generated for CPANSec. The issue has been assigned CVE-2026-19873, and has been added here publicly as per request from Dean Hamstead.

When a Repeatable element has counter_name set, Element/Repeatable.pm:279-282 takes the repeat count straight from the query string, validating only that it is a positive integer, and :290 passes it to repeat(), whose loops at :103 and :193 deep-clone the block's whole child subtree once per iteration. There is no upper bound, and no attribute an application could set to impose one.

my $input = $form->query->param($counter_name);

if ( defined $input && $input =~ /^[1-9][0-9]*\z/ ) {
$count = $input;
}

Element::Repeatable::process runs from HTML::FormFu::process() on every request and reads the counter before the submitted / not-submitted decision, so GET /form?count=N reaches it with no session, no authentication, no POST body and no submitted field values.

Cost is super-linear rather than linear: each cloned field's constraints call HTML::FormFu::Constraint::_find_field_value, which walks the entire element tree via get_fields({ nested_name => ... }) once per constraint. Measured on 2.07 under perl 5.40 with one Text field and one Required constraint in the block — the shape t/repeatable/constraints/required.yml uses — count=500 costs 1.0s CPU, 1000 4.1s, 2000 18.9s and 4000 98.2s, so doubling the parameter multiplies CPU by 4-5x and a five-digit value is CPU-hours from a single request. Removing the constraint makes it linear and cheap, which isolates the multiplier. Nested Repeatables are the memory variant and multiply: outer_count=100&inner_count=100 builds 10,000 fields and 95 MB RSS from two three-digit numbers, and that nesting is a shipped example (t/nested/elements/repeatable_repeatable.yml).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions