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::Help::Cookbook - Recipes for Yancy apps

VERSION

version 1.065

How can I limit which schemas and fields a user can edit inside the Yancy editor?

Create another instance of the Yancy editor using Yancy::Plugin::Editor, passing in a new route, a moniker, and the exact schemas and fields you want to allow.

# Allow content editors to only edit the title, content, and
# content_html of blog posts
my $schema = app->yancy->schema;
my $editable_properties = {
    %{ $schema->{blog_posts}{properties} }{qw(
        blog_post_id title content content_html
    )},
};
app->yancy->plugin( Editor => {
    backend => app->yancy->backend,
    route => '/edit',
    require_user => {
        -bool => 'is_editor',
    },
    schema => {
        blog_posts => {
            %{ $schema->{blog_posts} },
            properties => $editable_properties,
        },
    },
} );

See https://github.com/preaction/Yancy/tree/master/eg/limited-editor for the complete example.

How do I handle custom forms for searching or filtering content?

To handle a custom search form for the Yancy controller "list" action there are two options:

1. Use an under intermediate destination to process the form and set the filter stash

In this option, we use Mojolicious's "under" route to handle the form before the final action is called.

# Download this example: https://github.com/preaction/Yancy/tree/master/eg/cookbook/custom-filter-lite.pl
use Mojolicious::Lite -signatures;
# Download log.sqlite3: https://github.com/preaction/Yancy/tree/master/eg/cookbook/log.sqlite3
plugin Yancy => { backend => 'sqlite:log.sqlite3', read_schema => 1 };
under sub( $c ) {
    my $levels = $c->every_param( 'log_level' );
    if ( @$levels ) {
        # Include only log levels requested
        $c->stash( filter => { log_level => $levels } );
    }
    return 1;
};
get '/' => {
    controller => 'Yancy',
    action => 'list',
    schema => 'log',
    template => 'log',
};
app->start;
__DATA__
@@ log.html.ep
%= form_for current_route, begin
    % for my $log_level ( qw( debug info warn error ) ) {
        %= label_for "log_level_$log_level", begin
            %= ucfirst $log_level
            %= check_box log_level => $log_level
        % end
    % }
    %= submit_button 'Filter'
% end
%= include 'yancy/table'
2. Create a custom controller action to process the form and then call the "list" action

In this option, we extend the Yancy controller to add our own action. Then, we can call the action we want to end up at (in this case, the "list" action).

# Download this example: https://github.com/preaction/Yancy/tree/master/eg/cookbook/custom-filter-full.pl
use Mojo::Base -signatures;
package MyApp::Controller::Log {
    use Mojo::Base 'Yancy::Controller::Yancy', -signatures;
    sub list_log( $self ) {
        my $levels = $self->every_param( 'log_level' );
        if ( @$levels ) {
            # Include only log levels requested
            $self->stash( filter => { log_level => $levels } );
        }
        return $self->SUPER::list;
    }
}

package MyApp {
    use Mojo::Base 'Mojolicious', -signatures;
    sub startup( $self ) {
        push @{ $self->renderer->classes }, 'main';
        push @{ $self->routes->namespaces }, 'MyApp::Controller';

        # Download log.db: http://github.com/preaction/Yancy/tree/master/eg/cookbook/log.sqlite3
        $self->plugin( Yancy => {
            backend => 'sqlite:log.sqlite3',
            read_schema => 1,
        } );

        $self->routes->get( '/' )->to(
            controller => 'Log',
            action => 'list_log',
            schema => 'log',
            template => 'log',
        );
    }
}

Mojolicious::Commands->new->start_app( 'MyApp' );
__DATA__
@@ log.html.ep
%= form_for current_route, begin
    % for my $log_level ( qw( debug info warn error ) ) {
        %= label_for "log_level_$log_level", begin
            %= ucfirst $log_level
            %= check_box log_level => $log_level
        % end
    % }
    %= submit_button 'Filter'
% end

How can I allow users to create arbitrary pages in the Yancy editor?

Create a schema for the pages (perhaps, named pages). This schema must at least have an ID (perhaps in page_id), a path (in a path field), and some content (in a content field). We should use the path field as Yancy's ID field so that we can more easily look up the pages.

# Download this database: https://github.com/preaction/Yancy/tree/master/eg/cookbook/pages.sqlite3
use Mojolicious::Lite -signatures;
plugin Yancy => {
    backend => 'sqlite:pages.sqlite3',
    schema => {
        pages => {
            title => 'Pages',
            description => 'These are the pages in your site.',
            'x-id-field' => 'path',
            required => [qw( path content )],
            properties => {
                page_id => {
                    type => 'integer',
                    readOnly => 1,
                },
                path => {
                    type => 'string',
                },
                content => {
                    type => 'string',
                    format => 'html',
                },
            },
        },
    },
};

Once we have a schema, we need to render these pages. We want these pages to show up when the user visits the page's path, so we need a route that captures everything. Because our route captures everything, it should be the last route we declare (Mojolicious routes are checked in-order for matching). We also want to allow a default path of "index", so we give a default value for the path stash.

app->routes->get( '/*path', { path => 'index' } )->to({
    controller => 'Yancy',
    action => 'get',
    schema => 'pages',
    template => 'page',
});

Now we need a template to display the content. There isn't much to this template:

@@ page.html.ep
%== $item->{content}

View the example of user-editable pages

If you want your users to use Markdown instead of HTML, add another field for the Markdown (called markdown), and have the editor render the Markdown into HTML in the content field.

use Mojolicious::Lite -signatures;
# Download this database: https://github.com/preaction/Yancy/tree/master/eg/cookbook/pages-md.sqlite3
plugin Yancy => {
    backend => 'sqlite:pages-markdown.sqlite3',
    schema => {
        pages => {
            title => 'Pages',
            description => 'These are the pages in your site.',
            required => [qw( path markdown )],
            properties => {
                page_id => {
                    type => 'integer',
                    readOnly => 1,
                },
                path => {
                    type => 'string',
                },
                markdown => {
                    type => 'string',
                    format => 'markdown',
                    'x-html-field' => 'content',
                },
                content => {
                    type => 'string',
                    format => 'html',
                },
            },
        },
    },
};

View the example of pages with Markdown

AUTHOR

Doug Bell <preaction@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2020 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.