Security Advisories (9)
CVE-2020-11022 (2020-04-29)

In jQuery versions greater than or equal to 1.2 and before 3.5.0, passing HTML from untrusted sources - even after sanitizing it - to one of jQuery's DOM manipulation methods (i.e. .html(), .append(), and others) may execute untrusted code. This problem is patched in jQuery 3.5.0.

CVE-2020-11023 (2020-04-29)

In jQuery versions greater than or equal to 1.0.3 and before 3.5.0, passing HTML containing <option> elements from untrusted sources - even after sanitizing it - to one of jQuery's DOM manipulation methods (i.e. .html(), .append(), and others) may execute untrusted code. This problem is patched in jQuery 3.5.0.

CVE-2019-11358 (2019-04-20)

jQuery before 3.4.0, as used in Drupal, Backdrop CMS, and other products, mishandles jQuery.extend(true, {}, ...) because of Object.prototype pollution. If an unsanitized source object contained an enumerable __proto__ property, it could extend the native Object.prototype.

CVE-2015-9251 (2018-01-18)

jQuery before 3.0.0 is vulnerable to Cross-site Scripting (XSS) attacks when a cross-domain Ajax request is performed without the dataType option, causing text/javascript responses to be executed.

CVE-2011-4969 (2013-03-08)

Cross-site scripting (XSS) vulnerability in jQuery before 1.6.3, when using location.hash to select elements, allows remote attackers to inject arbitrary web script or HTML via a crafted tag.

CVE-2012-6708 (2018-01-18)

jQuery before 1.9.0 is vulnerable to Cross-site Scripting (XSS) attacks. The jQuery(strInput) function does not differentiate selectors from HTML in a reliable fashion. In vulnerable versions, jQuery determined whether the input was HTML by looking for the '<' character anywhere in the string, giving attackers more flexibility when attempting to construct a malicious payload. In fixed versions, jQuery only deems the input to be HTML if it explicitly starts with the '<' character, limiting exploitability only to attackers who can control the beginning of a string, which is far less common.

CVE-2020-7656 (2020-05-19)

jquery prior to 1.9.0 allows Cross-site Scripting attacks via the load method. The load method fails to recognize and remove "<script>" HTML tags that contain a whitespace character, i.e: "</script >", which results in the enclosed script logic to be executed.

CVE-2019-5428

Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_, constructor and prototype. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.

CVE-2014-6071 (2018-01-16)

jQuery 1.4.2 allows remote attackers to conduct cross-site scripting (XSS) attacks via vectors related to use of the text method inside after.

NAME

Yancy::Controller::Yancy::MultiTenant - A controller to show a user only their content

VERSION

version 1.088

SYNOPSIS

use Mojolicious::Lite;
plugin Yancy => {
    schema => {
        blog => {
            properties => {
                id => { type => 'integer' },
                user_id => { type => 'integer' },
                title => { type => 'string' },
                html => { type => 'string' },
            },
        },
    },
};

app->routes->get( '/user/:user_id' )->to(
    'yancy-multi_tenant#list',
    schema => 'blog',
    template => 'index'
);

__DATA__
@@ index.html.ep
% for my $item ( @{ stash 'items' } ) {
    <h1><%= $item->{title} %></h1>
    <%== $item->{html} %>
% }

DESCRIPTION

This module contains routes to manage content owned by users. When paired with an authentication plugin like Yancy::Plugin::Auth::Basic, each user is allowed to manage their own content.

This controller extends Yancy::Controller::Yancy to add filtering content by a user's ID.

METHODS

list

$routes->get( '/:user_id' )->to(
    'yancy-multi_tenant#list',
    schema => $schema_name,
    template => $template_name,
);

This method is used to list content owned by the given user (specified in the user_id stash value).

Input Stash

This method extends "list" in Yancy::Controller::Yancy and adds the following configuration and stash values:

user_id

The ID of the user whose content should be listed. Required. Should match a value in the user_id_field.

user_id_field

The field in the item that holds the user ID. Defaults to user_id.

get

$routes->get( '/:user_id/:id' )->to(
    'yancy-multi_tenant#get',
    schema => $schema_name,
    template => $template_name,
);

This method is used to show a single item owned by a user (given by the user_id stash value).

Input Stash

This method extends "get" in Yancy::Controller::Yancy and adds the following configuration and stash values:

user_id

The ID of the user whose content should be listed. Required. Should match a value in the user_id_field.

user_id_field

The field in the item that holds the user ID. Defaults to user_id.

set

$routes->any( [ 'GET', 'POST' ] => '/:id/edit' )->to(
    'yancy#set',
    schema => $schema_name,
    template => $template_name,
);

$routes->any( [ 'GET', 'POST' ] => '/create' )->to(
    'yancy#set',
    schema => $schema_name,
    template => $template_name,
    forward_to => $route_name,
);

This route creates a new item or updates an existing item in a schema. If the user is making a GET request, they will simply be shown the template. If the user is making a POST or PUT request, the form parameters will be read, the data will be validated against the schema configuration, and the user will either be shown the form again with the result of the form submission (success or failure) or the user will be forwarded to another place.

This method does not authenticate users. User authentication and authorization should be performed by an auth plugin like Yancy::Plugin::Auth::Basic.

Input Stash

This method extends "set" in Yancy::Controller::Yancy and adds the following configuration and stash values:

user_id

The ID of the user whose content is being edited. Required. Will be set in the user_id_field.

user_id_field

The field in the item that holds the user ID. Defaults to user_id. This field will be filled in with the user_id stash value.

delete

$routes->any( [ 'GET', 'POST' ], '/delete/:id' )->to(
    'yancy#delete',
    schema => $schema_name,
    template => $template_name,
    forward_to => $route_name,
);

This route deletes an item from a schema. If the user is making a GET request, they will simply be shown the template (which can be used to confirm the delete). If the user is making a POST or DELETE request, the item will be deleted and the user will either be shown the form again with the result of the form submission (success or failure) or the user will be forwarded to another place.

This method does not authenticate users. User authentication and authorization should be performed by an auth plugin like Yancy::Plugin::Auth::Basic.

Input Stash

This method extends "delete" in Yancy::Controller::Yancy and adds the following configuration and stash values:

user_id

The ID of the user whose content is being edited. Required. Will be set in the user_id_field.

user_id_field

The field in the item that holds the user ID. Defaults to user_id. This field will be filled in with the user_id stash value.

EXAMPLES

To use this controller when the URL displays a username and the content uses an internal ID, you can use an under route to map the username in the path to the ID:

my $user_route = app->routes->under( '/:username', sub {
    my ( $c ) = @_;
    my $username = $c->stash( 'username' );
    my @users = $c->yancy->list( user => { username => $username } );
    if ( my $user = $users[0] ) {
        $c->stash( user_id => $user->{id} );
        return 1;
    }
    return $c->reply->not_found;
} );

# /:username - List blog posts
$user_route->get( '' )->to(
    'yancy-multi_tenant#list',
    schema => 'blog',
    template => 'blog_list',
);
# /:username/:id/:slug - Get a single blog post
$user_route->get( '/:id/:slug' )->to(
    'yancy-multi_tenant#get',
    schema => 'blog',
    template => 'blog_view',
);

To build a website where content is only for the current logged-in user, combine this controller with an auth plugin like Yancy::Plugin::Auth::Basic. Use an under route to set the user_id from the current user.

app->yancy->plugin( 'Auth::Basic', {
    route => any( '' ), # All routes require login
    schema => 'user',
    username_field => 'username',
    password_digest => { type => 'SHA-1' },
} );

my $user_route = app->yancy->auth->route->under( '/', sub {
    my ( $c ) = @_;
    my $user = $c->yancy->auth->current_user;
    $c->stash( user_id => $user->{id} );
    return 1;
} );

# / - List todo items
$user_route->get( '' )->to(
    'yancy-multi_tenant#list',
    schema => 'todo_item',
    template => 'todo_list',
);

SEE ALSO

Yancy::Controller::Yancy, Mojolicious::Controller, Yancy

AUTHOR

Doug Bell <preaction@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2021 by Doug Bell.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.