From 0fe45119dffaf785665c9671effa4e8e421a5f51 Mon Sep 17 00:00:00 2001 From: Bkeenke Date: Mon, 6 Jul 2026 21:00:44 +0300 Subject: [PATCH] =?UTF-8?q?bk:=20=D1=84=D0=B8=D0=BA=D1=81=20=D0=B1=D0=B5?= =?UTF-8?q?=D0=B7=D0=BE=D0=BF=D0=B0=D1=81=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=8A=D0=B5=D0=BA=D1=86=D0=B8=D0=B8=20=D1=87=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B7=20fields?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/Core/Sql/Data.pm | 11 ++++++----- app/lib/Core/USObject.pm | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/lib/Core/Sql/Data.pm b/app/lib/Core/Sql/Data.pm index d27c3093..66dd3934 100644 --- a/app/lib/Core/Sql/Data.pm +++ b/app/lib/Core/Sql/Data.pm @@ -757,19 +757,20 @@ sub list_for_api { my $method = $args{admin} ? '_list' : 'list'; # Validate fields against structure to prevent SELECT injection. - # Complex expressions (containing SQL syntax like parentheses, wildcards or dots) - # are treated as trusted internal code and passed through unchanged. + # Trust is decided by the CLASS (trusted_fields_passthrough), never by the + # shape of the value itself - `fields` may come straight from an HTTP query + # string, so a class must opt in explicitly (and must guarantee it never + # forwards a client-supplied `fields` value unchanged) to bypass sanitizing. my $fields; if ( $args{fields} && $args{fields} ne '*' && $self->can('structure') ) { - if ( $args{fields} =~ /[().*]/ ) { - # Internal trusted SQL expression — pass through unchanged + if ( $self->can('trusted_fields_passthrough') && $self->trusted_fields_passthrough ) { $fields = $args{fields}; } else { my %structure = %{ $self->structure }; my @safe = grep { exists $structure{$_} } split /\s*,\s*/, $args{fields}; $fields = @safe ? join(', ', map { "`$_`" } @safe) : undef; } - } elsif ( $args{fields} ) { + } elsif ( $args{fields} && ( $args{fields} eq '*' || !$self->can('structure') ) ) { $fields = $args{fields}; } diff --git a/app/lib/Core/USObject.pm b/app/lib/Core/USObject.pm index 30da0022..fd70f75f 100644 --- a/app/lib/Core/USObject.pm +++ b/app/lib/Core/USObject.pm @@ -121,6 +121,8 @@ sub _list { return $self->SUPER::_list( %args ); } +sub trusted_fields_passthrough { return 1 } + sub list_for_api { my $self = shift; my %args = (