Drupal Planet

Subscribe to Drupal Planet feed
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 20 hours 46 min ago

Morpht: Drupal 8 Configuration - Part 2: How the API works

May 13, 2019 - 06:04
Background

We live in an age of Drupal complexity. In the early days of Drupal, many developers would have a single Drupal instance/environment (aka copy) that was their production site, where they would test out new modules and develop new functionality. Developing on the live website however sometimes met with disastrous consequences when things went wrong! Over time, technology on the web grew, and nowadays it's fairly standard to have a Drupal project running on multiple environments to allow site development to be run in parallel to a live website without causing disruptions. New functionality is developed first in isolated private copies of the website, put into a testing environment where it is approved by clients, and eventually merged into the live production site.

While multiple environments allow for site development without causing disruptions on the live production website, it introduces a new problem; how to ensure consistency between site copies so that they are all working with the correct code.

This series of articles will explore the Configuration API, how it enables functionality to be migrated between multiple environments (sites), and ways of using the Configuration API with contributed modules to effectively manage the configuration of a project. This series will consist of the following posts:

Part 1 gives the background of the Configuration API, as well as discusses some terminology used within this article, so it's worth a read before beginning this article.

Active configuration is in the database

In Drupal 8, configuration used at runtime is stored in the database. The values in the database are known as active configuration. In Drupal 7, configuration was known as settings, and stored in the {variable} table. In Drupal 8, configuration is stored in the {config} table. The active configuration is used at runtime by Drupal when preparing responses.

Configuration is backed up to files

The Configuration API enables the ability to export the active database configuration into a series of YML files. These files can also be imported into the database. This means that a developer can create a new Field API field on their local development environment, export the configuration for the new field to files, push those files to to the production environment, then import the configuration into the production environment's active configuration in the database.

The configuration values in the database are the live/active values, used by Drupal when responding to requests. The YMLfiles that represent configuration are not required, and are not used at run-time. In fact, in a new system the configuration files don't even exist until/unless someone exports the active configuration from the database. The configuration files are a means to be able to back up and/or migrate configuration between environments. Configuration files are never used in runtime on a site.

Configuration architecture

Let's look at the Configuration API on a more technical level, using a real-world example. The Restrict IP module allows users to set a list of rules that whitelist or blacklist users based on their IP address. Upon visiting the module settings page, users are presented with a checkbox that allows them to enable/disable the module functionality.

From a data standpoint, checkboxes are booleans; they represent either a true or false value. When exporting the configuration of a site with the Restrict IP module enabled, the relevant configuration key will be saved with a value of either true or false to a .yml file. Modules are required to define the schema for any configuration the module creates. Developers can look at the configuration schema declarations to understand what file(s) will be created, and what values are accepted.

Modules declare the schema for their configuration in the [MODULE ROOT]/config/schema directory. In the case of the Restrict IP module, the schema file is restrict_ip/config/schema/restrict_ip.schema.yml. This file contains the following declaration:

restrict_ip.settings:
  type: config_object
  label: 'Restrict IP settings'
  mapping:
    enable:
      type: boolean
      label: 'Enable module'

Schema declarations tell the system what the configuration looks like. In this case, the base configuration object is restrict_ip.settings, from the first line. When this configuration is exported to file, the file name will be restrict_ip.settings.yml. In that file will be a declaration of either:

enable: true

Or:

enable: false

When the file restrict_ip.settings.yml is imported into the active configuration in another environment's database, the value for the enable key will be imported as defined in the file.

On top of this, enabled modules are listed in core.extension.yml, which is the configuration that tracks which modules are enabled in a given environment. When the Restrict IP module is enabled in one environment, and configuration files exported from that environment are imported into a different Drupal environment, the Restrict IP module will be enabled due to its existence in core.extension.yml, and the setting enable will have a value of either true or false, depending on what the value was exported from the original environment.

Note that if you were to try to import the configuration without having the Restrict IP module in the codebase, an error will be thrown and the configuration import will fail with an error about the Restrict IP module not existing.

Summary

In this article, we looked at how the Drupal 8 Configuration API works on a technical level. We looked at how active configuration lives in the database, and can be exported to files which can then be imported back into the database, or migrated and imported to other Drupal environments. In part 3 of the series, Using the API, we will look at how to actually use the Configuration API, as well as some contributed modules that extend the functionality of the Configuration API, allowing for more effective management of Drupal 8 projects.

Matt Glaman: A proper introduction to Drupal Check

May 12, 2019 - 21:30
A proper introduction to Drupal Check Sunday 12, May 2019 mglaman You may have heard of Drupal Check. You may wonder what in the world it is or how it even came to be. I realized this went from an internal research and development task for a product, to open source contribution and then to an essential tool in the march toward Drupal 9. The timeline from January to DrupalCon in April has been pretty crazy, and I realized I have never done a proper blog post about Drupal Check.

Matt Glaman: ContribKanban 2019 update

May 12, 2019 - 06:45
ContribKanban 2019 update Saturday 11, May 2019 mglaman It seems that I do a roughly annual update for ContribKanban and what I plan on doing with it. This year I evaluated its future and roadmap and how it can be more useful for the community at large.

Chapter Three: Gated resources forms with webform and token

May 11, 2019 - 03:24

On several occasions clients have come to us asking for a form with a gated resource. They want the  resource (.pdf, .doc, .xls etc.) to be available to download after the user fills a form. In exchange for the visitor's valuable information, we provide them a file.

This is easily achievable in Drupal 8 with the Webform and Token modules.  At the time of creation of this blog post, I used Drupal version 8.7.0.

Vasily Yaremchuk: I have switched my Drupal 8 site to a static HTML site with Tome

May 11, 2019 - 02:00
I have switched my Drupal 8 site to a static HTML site with Tome

Many years ago I made my personal page on Drupal 7, as soon as Drupal 8 was released I have upgraded to this version. My personal site is just a page with my contacts and my blog. 

In truth, I do not always have enough time to write posts to my blog, as well as keep the core and modules up to date. Some times between the huge projects I have a frame to share my experience and to make some support tasks and improvements. 

So more than 99% of its life my personal site works as a simple static HTML site.

Does it make sense to use Drupal as a backend? 

Let's imagine the site is static at any time except the time when I want to edit it...

And it's possible with Tome. It's Drupal 8 module. You can get more information on the official site tome.fyi.

Let me show you my personal site abzats.com. It's a static HTML site. I don't have the permanent version of this site either hosted somewhere or locally. But I have a private repository of my Drupal site with configurations and content in flat files. 

Tome module allows exporting configurations in .yml files and content in .json files as well as install Drupal with those files without operating with the DataBase dump.

I have decided to put some changes on the site. I need to get the site locally, log in Drupal admin, make changes and generate a new version of my static site. That's it.  

Cloning the site:

$ git clone git@github.com:vasilyyaremchuk/personal.git

It's my private repository, that I have forked from https://github.com/drupal-tome/netlify-template

Coming to the folder:

$ cd personal

If you've taken a look at https://github.com/drupal-tome/netlify-template you could find that there is no core folder there. You have to run 

$ composer install 

to get all necessary dependencies. 

Install the site with drush:

$ drush tome:install

Run a local server with drush:

$ drush runserver

Make some changes in the admin area. A new password to login in admin provided after the previous action.

If all changes were done, we can stop the server and generate a static site:

$ drush tome:static --uri=http://abzats.com/

Attention! Don't forget to set the basic URL of your production site, otherwise, you can get incorrect links that point to your local environment in some places of the static site.

Now you have a new static version of the site and you can deploy it on your hosting.

Don't forget to update the repository with those changes:

$ git status

You can see that one file with content is changed. Let me commit those changes:

$ git add .

$ git commit -m "content changes"

$ git push

Finally, you can delete the local Drupal 8 site:

$ cd ..

$ rm -R personal

Vasyl Yaremchuk 05/10/2019

wishdesk.com: New Drupal Media Library interface: managing media with joy

May 10, 2019 - 22:50

The blend of usability and attractiveness exists — this is Media Library in Drupal 8.7 core. That’s what comes to mind when we see Drupal Media Library’s updated UI. Managing media on websites will now be easier and more enjoyable than before!

Drupal Media Library allows you to:

Roy Scholten: No one-offs

May 10, 2019 - 21:05
Sub title

Things seen here are configured there.

/sites/default/files/styles/large/public/things-shown-here-configured-there.png?itok=qSZb6N0L

An elaboration on underlying considerations that make simple suggestions as this one not so simple after all.

An important consideration when deciding whether to “add something to core” is that generally speaking, core doesn’t do one-offs. The underlying principle is not “make it do X” but “make it possible to make it do X (and X2, X3,…)

Linking from a create context to a configuration context

In this particular case we have a proposal to link to the screen where you can add new content types from the page that lists available content types to create content with. Or, in url speak: on /node/add, put a link to /admin/structure/types. Or once more: on the screen that lists existing content types that you can create content with, add a link to the screen that lets you define new content types.

Notice the distinction between “create content of type X” and “define a new type of content Y”. The first is a content creation task, the second is a content definition task (in Drupal jargon usually captured under “site building”). This distinction then should clarify why a link to define a new content type should not use the “blue + button” pattern on a screen that is in service of a content creation task.

Back to the “no one-offs” principle. Where and how can we add a link of this kind? To answer that question we should look for possible patterns. Is there a more generalised definition for the type of problem that this single link to elsewhere wants to solve?

The example is: put a link to the content type definition area on the screen that lists already available types to create content with. Restated more generally: link to that area of the Drupal admin where the things on this screen are configured.

Connecting the dots is important

You know those links at the bottom of product pages in an online store: “people who bought this item also bought X, Y and Z”. In our case it’s more like “Things seen here are configured there.

I noticed a sort of similar pattern in the Android OS settings pages, where the screen ends with suggestions of related topics to the ones already shown. It’s a way to provide meaningful next places to go if the current page didn’t offer what you were looking for (and is of course a symptom of how many settings there are in the first place).

“Things seen here are defined there.

If we can find more examples of where this would be meaningful and helpful then we might have a good case for introducing a new user interface pattern. See image for some initial examples.

Tags Drupal drupalplanet

Morpht: Drupal 8 Configuration - Part 1: The Configuration API

May 10, 2019 - 09:18
Background

We live in an age of Drupal complexity. In the early days of Drupal, many developers would have a single Drupal instance/environment (aka copy) that was their production site, where they would test out new modules and develop new functionality. Developing on the live website however sometimes met with disastrous consequences when things went wrong! Over time, technology on the web grew, and nowadays it's fairly standard to have a Drupal project running on multiple environments to allow site development to be run in parallel to a live website without causing disruptions. New functionality is developed first in isolated private copies of the website, put into a testing environment where it is approved by clients, and eventually merged into the live production site.

While multiple environments allow for site development without causing disruptions on the live production website, it introduces a new problem; how to ensure consistency between site copies so that they are all working with the correct code.

This series of articles will explore the Configuration API, how it enables functionality to be migrated between multiple environments (sites), and ways of using the Configuration API with contributed modules to effectively manage the configuration of a project. This series will consist of the following posts:

  • Part 1: The Configuration API
  • Part 2: How the API works (coming soon)
  • Part 3: Using the API (coming soon)
  • Part 4: Extending the API with contributed modules (coming soon)
  • Part 5: Module developers and the API (coming soon)
Terminology

Before we get started, let's review some terminology. A Drupal project is the overall combination of the core codebase and all of the environments that are used for development of the project. An environment is a copy/clone of the website that is accessible at a unique domain name (URL). When most users on the web think of a website, they think of the environment accessed at a single URL, like google.com or facebook.com. These URLs are the entry to the live production environments for these websites. However, in addition to the production environment, large projects will have additional environments, where code is developed and tested before being deployed to the production environment. The combination of these environments make up the project. Drupal 8 is built to enable developers to migrate functionality for a project between environments, using the Configuration API.

Components of a Drupal environment

What makes up an environment of a Drupal project? In other words, when making a 'copy' of a Drupal site, what are the elements that need to be migrated/copied to create that copy? A Drupal environment consists of the following elements:

  1. Codebase: At the core of any Drupal system is codebase that makes up the 'engine' that runs Drupal. The codebase of any Drupal site consists of Drupal core, modules (both contributed and custom), and themes (again, both contributed and custom). The codebase is a series of files, and these files provide the functionality of a Drupal site.
  2. Configuration: Configuration is the collection of settings that define how the project will implement the functionality provided by the codebase. The codebase provides the abstract functionality to create things like content types, fields and taxonomies. Developers configure a Drupal site through the admin interface, to create the actual content types, fields, and taxonomies used in the project, that will allow end-users to do things like create pages or make comments. As developers build out the functionality of the project through the admin interface, the settings they choose are saved as the configuration for that environment. Configuration is environment-specific, and the Configuration API provides a means of migrating configuration between environments.
  3. Content: Content is the data on a site that is specific to the given environment. Content may be created by end-users, or by content admins. While content, like configuration, sometimes needs to be migrated between environments, content should be considered environment-specific. The Migrate API provides a means of migrating content between environments.
  4. Uploaded files: Most Drupal projects will have files uploaded as content. These are not part of the codebase that provides the functionality of the system, rather they are files that are to be provided to end users. Examples are images, audio/video files and PDFs.
  5. Third party technologies: Drupal 8 is a hub framework, built to integrate with 3rd party libraries, APIs, softwares, and other technologies. For example, a project may use a 3rd party CSS/JS framework, or swap out the default database caching backend to a Redis caching backend, which provides significant performance improvements. While these third party technologies are not part of Drupal, often the technologies will be required in each environment for the project to run.

The above five elements together make up a Drupal environment. The environment is a fully-functioning Drupal copy (instance), with its own configuration and content. Each environment will have its own domain (URL) at which the environment can be accessed.

Types of environments

Typical projects these days will have a minimum of three environments:

  1. Production environment: The main live environment that end users will use.
  2. Staging environments: One or more environments on which site owners can test new functionality or bug fixes before they are deployed to the production environment.
  3. Development environments, where new functionality can be developed in isolation. Development environments may be publicly accessible, or may only exist on a developers computer, not accessible to the outside internet.
Content and configuration - both stored in the database

A major issue that existed with all versions of Drupal core up to and including Drupal 7, was that content and configuration were both stored in the database, and there was no way to separate them. This made it difficult to manage configuration changes, such as adding a field to a content type, between multiple environments. There was no way to export the configuration for that single field, so to ensure consistency full databases were migrated. The problem is that database migrations are an all-or-nothing venture; when migrating from one environment to another, the entire database of the source environment overwrote the entire database on the target environment, meaning all content and configuration was overridden on the target environment.

This opens up a problem though. Imagine this scenario:

  1. A developer copies the production database to their local computer.
  2. Someone creates new content on the production environment, that becomes part of the database.
  3. The developer adds a new field on their local environment.
  4. The developer migrates their local database to the production environment, overwriting all configuration and content on the production environment.

With the above scenario, the new field created on the developer's local environment is now on the production environment, however the content created in step 2 is overwritten and lost. As such, the above process is untenable. Databases cannot be migrated 'up' (to production) after a site has gone live. They can only be migrated 'down' (from production).

To overcome this problem, a common way to make changes to configuration before Drupal 8 was to make configuration changes on the production environment, then copy the production environment's database down to the other environments. For example, if a developer was writing code that depended on a new field, rather than create the field on their local development environment, they would create the field on the production environment, then copy the production environment database down to their local development environment. Now the field exists on both the production environment as well as their development environment. This solution works, but is akin to killing a mosquito with a sledgehammer - it's overkill. The developer did not need the whole database, only the configuration for that single field. And any changes they had already made in their own environment, such as content for testing, is now wiped out with data from the production environment.

While this process worked (and still does continue to work for many projects), it was not ideal. It led to issues where database migrations had to be coordinated with clients and other developers to ensure that it was safe to wipe out content or configuration someone else may still be working with.

The Configuration API

The Drupal 8 Configuration API was created to overcome the above issue, so that developers could migrate configuration - such as Field API fields, content types, and taxonomies - between environments, without having to overwrite the entire database. It decoupled configuration from content. To understand how it makes things better, let's again review the components of a Drupal site, and the storage mechanisms behind them:

  • Codebase (files)
  • Configuration (database)
  • Content (database)
  • Uploaded files (files)

With the Configuration API, configuration can be exported into files, and these files can be migrated between environments and imported into the new environment. This means that we can now migrate individual items of configuration without having to overwrite the entire database. The Configuration API decouples configuration from content. In the next parts of this series, we will explore how the API work

Note 1: the Drupal 7 Features module essentially does the same thing, and though the methodology is different, many of the concepts in the following articles will be relevant to that module as well.

Note 2: the Drupal 8 Migrate API was developed in parallel to the Configuration API, allowing for content also to be migrated, again without overwriting the entire database.

Summary

In this article, we looked at an overview of the Configuration API to understand what it is, and why it was created. After reading this article, you should have an understanding of what a Drupal environment is, and what it consists of. You should understand that in Drupal 8, configuration is stored in the database, but can be exported to files, which can then be used to migrate content between environments. In Part 2 - How the API works, we will take a closer, more technical look at how the API works, and in Part 3 - Using the API, we will discuss how to use the API, and some contributed modules that extend its functionality.

DrupalCon News: Reflections from DrupalCon Seattle’s Grant & Scholarship Recipients

May 9, 2019 - 23:56

What an event this last DrupalCon was! Thanks to all who joined us in April for DrupalCon Seattle 2019.

In planning this event, more funds than ever before — 30 percent more, to be exact — were allocated for grants and scholarships. This tied in with the overall aim of having a cross-section of attendees, all of whom play a part in contributing and advancing the Drupal Project. Funding for grants and scholarships is from the support of our conference partners, as well as conference registrations.

Sven Decabooter: How to make a Drupal 8 local task title dynamic

May 9, 2019 - 22:00
How to make a Drupal 8 local task title dynamic

When defining local tasks (= tabs) in your Drupal 8 modules, you can specify a title for the tab via the 'title' property in your [MODULENAME].links.task.yml file.

However, in some cases you might want to make the task title dynamic, e.g. depending on the context of the entity where the tab is displayed.
This can be achieved by overriding the \Drupal\Core\Menu\LocalTaskDefault class with your own class for that tab.

Here is an example that uses a callback function to dynamically set the title, both for the route and the local task:

 

  1. Add the dynamic logic to your controller File: my_module/src/Controller/DynamicTabController.php
    <?php
    
    namespace Drupal\my_module\Controller;
    
    use Drupal\Core\Controller\ControllerBase;
    use Drupal\node\NodeInterface;
    
    /**
     * Controller for our dynamic tab.
     */
    class DynamicTabController extends ControllerBase {
    
      /**
       * Route title callback.
       *
       * @param \Drupal\node\NodeInterface $node
       *   The node entity.
       *
       * @return string
       *   The title.
       */
      public function getDynamicTabTitle(NodeInterface $node) {
        return $this->t('Dynamic tab for @type', ['@type' => $node->bundle()]);
      }
    
    }
    
  2. Use the dynamic title callback for your route File: my_module/my_module.routing.yml
    entity.node.dynamic_tab:
      path: '/node/{node}/dynamic_tab'
      defaults:
        _entity_form: 'node.dynamic_tab'
        _title_callback: '\Drupal\my_module\Controller\DynamicTabController::getDynamicTabTitle'
      requirements:
        _entity_access: 'node.view'
  3. Add your custom LocalTask plugin File: my_module/src/Plugin/Menu/LocalTask/DynamicTabLocalTask.php
    <?php
    
    namespace Drupal\my_module\Plugin\Menu\LocalTask;
    
    use Drupal\Core\Menu\LocalTaskDefault;
    use Drupal\Core\StringTranslation\StringTranslationTrait;
    use Drupal\node\NodeInterface;
    use Drupal\my_module\Controller\DynamicTabController;
    use Symfony\Component\HttpFoundation\Request;
    
    /**
     * Local task plugin to render dynamic tab title dynamically.
     */
    class DynamicTabLocalTask extends LocalTaskDefault {
    
      use StringTranslationTrait;
    
      /**
       * {@inheritdoc}
       */
      public function getTitle(Request $request = NULL) {
        $node = $request->attributes->get('node');
        if ($node instanceof NodeInterface) {
          $controller = new DynamicTabController();
          return $controller->getDynamicTabTitle($node);
        }
        return $this->t('Default');
      }
    
    }
    
  4. Set your custom class for your local task File: my_module/my_module.links.task.yml
    entity.node.dynamic_tab:
      route_name: entity.node.dynamic_tab
      base_route: entity.company.canonical
      title: 'Default'
      class: '\Drupal\my_module\Plugin\Menu\LocalTask\DynamicTabLocalTask'

Now the dynamic title will be used to render your tab name, and the tab page title.

Sven Decabooter Thu, 05/09/2019 - 17:00

Specbee: Drupal 8.7 Features (What’s New and Why Should You Care)

May 9, 2019 - 20:50
How do you stay ahead of your competition? Easy - Be relevant. Address your audience’s pain points. Repeat. With the adoption of the continuous innovation model, Drupal is doing that and more. Drupal 8.7 was released on May 1st following the 6 months release cycle for Drupal 8. We saw huge improvements in Drupal 8.6 which was a big release. With 8.7, it just got better - With more stable modules ready to be used on productions and other interesting out-of-the-box features.

ThinkShout: Recognizing Insecure Drupal Code

May 9, 2019 - 19:00

Within the Drupal community, it seems like many developers are interested in ensuring their modules and themes are secure, but don’t really know what insecure code looks like. I’ve personally found a lot of resources that tell you about security best practices, but don’t dive deeper into common missteps and their consequences.

Drupal 8 is the most modern and secure release of Drupal yet, which leads developers to expect that all Drupal 8 APIs are perfectly safe to use. While it’s great that Drupal has earned that reputation, there are still plenty of ways to leave your site vulnerable.

In this blog I’ll go through examples of insecure code that I’ve seen doing security research and review into Drupal 8, which will hopefully make it easier for you to know what to look for when reviewing your own code.

So you want to render HTML…

Outputting HTML is Drupal’s bread and butter, but if you’re rendering user input you may be vulnerable to cross site scripting, otherwise known as XSS.

XSS occurs when a malicious user identifies an exploit that allows user input to be executed as Javascript. Then, typically, an attacker leads someone without higher privileges (an administrator) to trigger the exploit. At that point, an attacker can do anything the administrator can do - add more administrator accounts, delete content, download sensitive data, and potentially use a chained exploit to execute server-side code.

Twig has your back

With Drupal 8’s implementation of Twig, all variables rendered normally (within curly braces) are automatically filtered. The attributes object, which is often used in Twig, is also generally safe. For example, trying to add a malicious attribute with code like:

<b {{ attributes.addClass('"onmouseover="alert(1)"') }}>Hello</b>

Will render safely as:

<b class="&quot;onload=&quot;alert&quot;">Hello</b>
Unquoted attributes

Twig isn’t inherently immune to XSS. If you don’t wrap attributes in double quotes, for instance, user input could render a malicious attribute. For example, if you have a template like:

<b class={{ configurable_class }}>Hello</b>

And pass in a class configured by a user:

$variables['configurable_class'] = 'foo onclick=alert(bar)';

The final, unsafe HTML will be:

<b class=foo onclick=alert(bar)>Hello</b>

This is because variables have HTML special characters escaped, but aren’t aware of the context they’re rendered in. onclick=alert(bar) on its own is completely safe, but when inside an opening HTML tag can trigger XSS.

The raw filter

One of the filters that comes with Twig, raw, marks a value as being safe and does not escape it. That means that if you ever see something like:

{{ variable | raw }}

In your templates, that could lead to an XSS vulnerability. There are very few use cases for raw, so if you can avoid using it completely you should.

Misusing render arrays

Render and form arrays in Drupal can also be misused to allow XSS. For example, you may know that HTML like this executes arbitrary Javascript on click:

<a href="javascript:alert()">Click me!</a>

And if you’re using url or link objects or render elements, this will be rendered as:

<a href="alert()">Click me!</a>

Which is safe. However, if you’re not using the url or link APIs, Drupal doesn’t have the context to know that the “href” attribute could be unsafe, and will render it without escaping. For example, this code:

$build = ['#type' => 'html_tag', '#tag' => 'a', 'Hello'];
$build['#attributes']['href'] = $user_input;

When provided this user input:

$user_input = 'javascript:alert("foo")';

Will render:

<a href="javascript:alert(\"foo\")">Hello</a>

Like the Twig attribute issue, this is a result of Drupal not being aware that untrusted data is being passed to potentially dangerous APIs. Here are some more examples of render arrays that allow XSS:

$build['#markup'] = $user_input;
$build['#allowed_tags'] = ['script'];
$build['#children'] = $user_input;
$build['#markup'] = t($user_input);
$build = ['#type' => 'inline_template', '#template' => $user_input];
Not filtering in Javascript

While the examples so far have been about backend code, XSS is commonly triggered from Javascript. Take this example, where the value of an input is passed to jQuery’s html function to display an error:

var value = $('input.title').val();
$('.error').html('<p>Invalid title "' + value + '"</p>');

Since the html function assumes the data you pass is safe, this could trigger XSS. A better way of approaching this is to use the text function, which escapes special characters:

var value = $('input.title').val();
$('.error').text('Invalid title "' + value + '"');

The most Drupal-y way to accomplish this would be to use the Drupal.t function, which accepts placeholders that are automatically escaped, and translates text:

var value = $('input.title').val();
$('.error').html(Drupal.t('<p>Invalid title "@title"</p>', {'@title': value});
Sniffing out XSS problems

In general, a good way to spot XSS is to question complexity wherever you see it. Look into your biggest forms and controllers and see if there’s anything odd using user input, and if so make an effort to exploit it. Also, if there’s any opportunity to use Twig instead of concatenating HTML in the backend, use Twig!

So you want to query the database…

Drupal comes with a database abstraction layer that saves you from writing SQL by hand, which has done a lot to prevent a type of vulnerability called SQL injection, otherwise known as SQLi.

SQLi occurs when a malicious user identifies an SQL query that can be unsafely modified by user input, allowing them to add arbitrary statements or additional queries onto an existing query. SQLi can allow attackers to read arbitrary sensitive data, insert arbitrary data, or even wipe existing data if they are able to.

Use the abstractions

The best advice when querying the database is to use Drupal’s database API wherever possible. Drupal has great documentation on how to properly use this API here: https://www.drupal.org/docs/8/api/database-api

The API is normally safe to use, but can be used unsafely in ways that aren’t clear to all Drupal developers.

Not using placeholders

There are cases where you need to write a query by-hand, which is fine unless that query uses user input, in which case you need to use placeholders. For example, this code has user input ($name) in the query string:

\Drupal::database()
  ->query("DELETE FROM people WHERE name = \"$name\"")
  ->execute();

If $name is set to a malicious value, like:

$name = 'myname" OR "" = "';

The final query ends up being:

DELETE FROM people WHERE name = "myname" OR "" = ""

Which in this example would delete everyone from the people table. The proper way to do this would be to use placeholders in your query string, and pass the user input as an argument:

\Drupal::database()
  ->query('DELETE FROM people WHERE name = :name', [
    ':name' => $name,
  ])
  ->execute();
Not escaping LIKE

Typically when using the database API, using the condition method and passing user input as the value is safe. However, if you are using the LIKE condition, you need to escape user input that may contain the wildcard character (%). For example, this code has user input ($name) in a LIKE condition:

$result = \Drupal::database()
  ->delete('people')
  ->condition('name', '%_' . $name, 'LIKE')
  ->execute();

If $name is set to a malicious value, like:

$name = '%';

The final query ends up being:

DELETE FROM people WHERE name LIKE "%_%"

Which would delete every row in the people table where the name included an underscore. The proper way to do this is to escape the user input using the escapeLike method, like so:

$database = \Drupal::database();
$result = $database
  ->delete('people')
  ->condition('name', '%_' . $database->escapeLike($name), 'LIKE')
  ->execute();
Trusting user operators

Passing user input as a condition value is generally safe, but passing it to other parts of the API like table names, column names, or condition operators is dangerous. For example, this code has user input ($operator) as a condition operator:

$result = \Drupal::database()
  ->select('people')
  ->condition('name', $name, $operator)
  ->execute();

If $operator is set to a malicious value, like:

$operator = 'IS NOT NULL)
UNION ALL SELECT SID,SSID FROM SESSIONS
JOIN USERS WHERE ("foo" <>';

The final query ends up being:

SELECT FROM people WHERE (name IS NOT NULL)
UNION ALL SELECT SID,SSID FROM SESSIONS
JOIN USERS WHERE ("foo" <> :name)

Which would query all session IDs from the sessions table, allowing user sessions to be hijacked.

To address this, compare the user input to a list of known valid SQL operators before using it in the query.

General SQL tips

If you use the database API in a typical, non-complex way, you’ll probably be fine. Just remember to use placeholders, escape user input when used in a LIKE statement or as an operator, and try to never write queries by hand.

So you want to write some code…

Beyond Drupal specific APIs, a lot of your code is just plain PHP, which comes with its own set of security issues. One last kind of exploit I’ll briefly cover is remote code execute, otherwise known as RCE.

RCE occurs when a malicious user identifies an exploit that allows user input to be executed as server-side code, most commonly by your runtime language (PHP) or the shell. RCE allows an attacker to do anything your web user can do, which could be everything from reading sensitive data, setting up a persistent backdoor, or using the compromised server to reach more servers on your network.

PHP, historically, has allowed for RCE in a lot of different ways, so there’s no golden rule to follow. Instead, watch out for some of the RCE classics:

Using user input to execute shell commands:

`magick convert $user_input output.png`;
shell_exec("magick convert $user_input output.png");

You could use the escapeshellarg function here to escape user input, but that isn’t foolproof as options (--foo=bar) are just wrapped in quotes, which in some command line applications is treated as a valid option. Validating the user input against a small set of allowed characters may be the best bet here, in addition to using escapeshellarg.

Using eval to execute dynamic PHP expressions:

eval("is_null($user_input)");

This allows arbitrary PHP to be executed and should not be used.

Using unserialize on data that could be entered by the user:

unserialize($user_input);

This allows for object injection, a vulnerability that can lead to RCE, and should be avoided if possible. Consider storing complex data as JSON instead, which is safe to use.

Without a deep experience in how RCE exploits are performed it’s hard to spot vulnerabilities, but you should review any code that has dynamic shell commands, eval, or unserialize with a high level of scrutiny.

A parting thought

Information like this can be daunting, but the best way to apply it to your work is to research common vulnerabilities, try a few exploits out, and make security a part of your company’s culture as well as code. Once you start thinking about security it’s hard to get it out of your head - does your company properly use encryption? Is two factor authentication enforced? How’s your office’s physical security? Being aware of these issues can lead to improvements that extend far beyond your custom code.

Freelock : Assessment of May 8 Drupal Security update SA-CORE-2019-007

May 9, 2019 - 03:12
Assessment of May 8 Drupal Security update SA-CORE-2019-007 John Locke Wed, 05/08/2019 - 14:12

New versions of Drupal core dropped today, to fix a file handling issue.

After assessing the patches, statements, and risks associated with this update, we have decided this is an important update to apply, but not urgent for most of the sites we manage.

Exploitation of the flaw takes two things:

Drupal Drupal Planet Security

myDropWizard.com: Drupal 6 core security update for SA-CORE-2019-007

May 9, 2019 - 00:31

As you may know, Drupal 6 has reached End-of-Life (EOL) which means the Drupal Security Team is no longer doing Security Advisories or working on security patches for Drupal 6 core or contrib modules - but the Drupal 6 LTS vendors are and we're one of them!

Today, there is a Moderately Critical security release for Drupal core to fix a vulnerability in the protections added in SA-CORE-2019-003. You can learn more in the security advisory:

Drupal core - Moderately Critical - Third-party Libraries - SA-CORE-2019-007

Here you can download the Drupal 6 patch to fix, or a full release ZIP or TAR.GZ.

If you have a Drupal 6 site, we recommend you update immediately! We have already deployed the patch for all of our Drupal 6 Long-Term Support clients. :-)

If you'd like all your Drupal 6 modules to receive security updates and have the fixes deployed the same day they're released, please check out our D6LTS plans.

Note: if you use the myDropWizard module (totally free!), you'll be alerted to these and any future security updates, and will be able to use drush to install them (even though they won't necessarily have a release on Drupal.org).

Security advisories: Drupal core - Moderately critical - Third-party libraries - SA-CORE-2019-007

May 8, 2019 - 23:56
Project: Drupal coreDate: 2019-May-08Security risk: Moderately critical 14∕25 AC:Complex/A:Admin/CI:All/II:All/E:Theoretical/TD:UncommonVulnerability: Third-party librariesDescription: 

This security release fixes third-party dependencies included in or required by Drupal core. As described in TYPO3-PSA-2019-007: By-passing protection of Phar Stream Wrapper Interceptor:

In order to intercept file invocations like file_exists or stat on compromised Phar archives the base name has to be determined and checked before allowing to be handled by PHP Phar stream handling. [...]

The current implementation is vulnerable to path traversal leading to scenarios where the Phar archive to be assessed is not the actual (compromised) file.

Solution: 

Install the latest version:

Versions of Drupal 8 prior to 8.6.x are end-of-life and do not receive security coverage.

Also see the Drupal core project page.

Reported By: Fixed By: 

TEN7 Blog's Drupal Posts: Episode 059: 2019 Twin Cities Drupal Camp

May 8, 2019 - 20:35

Chris Weber and Dan Moriarty, volunteer organizers for the 2019 Twin Cities Drupal Camp are today's podcast guests. We'll be talking about the changes to this year's TCDrupal Camp and fond memories of previous camps. 

TCDrupal Camp is a three-day conference for open source enthusiasts, designers, hackers, geeks, developers, UI experts, IT managers and anyone else that wants to find out more about Drupal. It’s a great place to learn, code, network and have fun with your fellow Drupalistas.

Dries Buytaert: Acquia acquires Mautic to create the Open Digital Experience Platform

May 8, 2019 - 20:05

I'm happy to announce today that Acquia acquired Mautic, an open source marketing automation and campaign management platform.

A couple of decades ago, I was convinced that every organization required a website — a thought that sounds rather obvious now. Today, I am convinced that every organization will need a Digital Experience Platform (DXP).

Having a website is no longer enough: customers expect to interact with brands through their websites, email, chat and more. They also expect these interactions to be relevant and personalized.

If you don't know Mautic, think of it as an alternative to Adobe's Marketo or Salesforce's Marketing Cloud. Just like these solutions, Mautic provides marketing automation and campaign management capabilities. It's differentiated in that it is easier to use, supports one-to-one customer experiences across many channels, integrates more easily with other tools, and is less expensive.

The flowchart style visual campaign builder you saw in the beginning of the Mautic demo video above is one of my favorite features. I love how it allows marketers to combine content, user profiles, events and a decision engine to deliver the best-next action to customers.

Mautic is a relatively young company, but has quickly grown into the largest open source player in the marketing automation space, with more than 200,000 installations. Its ease of use, flexibility and feature completeness has won over many marketers in a very short time: the company's top-line grew almost 400 percent year-over-year, its number of customers tripled, and Mautic won multiple awards for product innovation and customer service.

The acquisition of Mautic accelerates Acquia's product strategy to deliver the only Open Digital Experience Platform:

The pieces that make up a Digital Experience Platform, and how Mautic fits into Acquia's Open Digital Experience Platform. Acquia is strong in content management, personalization, user profile management and commerce (yellow blocks). Mautic adds or improves Acquia's multi-channel delivery, campaign management and journey orchestration capabilities (purple blocks).

There are many reasons why we like Mautic, but here are my top 3:

Reason 1: Disrupting the market with "open"

Open Source will disrupt every component of the modern technology stack. It's not a matter of if, it's when.

Just as Drupal disrupted web content management with Open Source, we believe Mautic disrupts marketing automation.

With Mautic, Acquia is now the only open and open source alternative to the expensive, closed, and stagnant marketing clouds.

I'm both proud and excited that Acquia is doubling down on Open Source. Given our extensive open source experience, we believe we can help grow Mautic even faster.

Reason 2: Innovating through integrations

To build an optimal customer experience, marketers need to integrate with different data sources, customer technologies, and bespoke in-house platforms. Instead of buying a suite from a single vendor, most marketers want an open platform that allows for open innovation and unlimited integrations.

Only an open architecture can connect any technology in the marketing stack, and only an open source innovation model can evolve fast enough to offer integrations with thousands of marketing technologies (to date, there are 7,000 vendors in the martech landscape).

Because developers are largely responsible for creating and customizing marketing platforms, marketing technology should meet the needs of both business users and technology architects. Unlike other companies in the space, Mautic is loved by both marketers and developers. With Mautic, Acquia continues to focus on both personas.

Reason 3: The same technology stack and business model

Like Drupal, Mautic is built in PHP and Symfony, and like Drupal, Mautic uses the GNU GPL license. Having the same technology stack has many benefits.

Digital agencies or in-house teams need to deliver integrated marketing solutions. Because both Drupal and Mautic use the same technology stack, a single team of developers can work on both.

The similarities also make it possible for both open source communities to collaborate — while it is not something you can force to happen, it will be interesting to see how that dynamic naturally plays out over time.

Last but not least, our business models are also very aligned. Both Acquia and Mautic were "born in the cloud" and make money by offering subscription- and cloud-based delivery options. This means you pay for only what you need and that you can focus on using the products rather than running and maintaining them.

Mautic offers several commercial solutions:

  • Mautic Cloud, a fully managed SaaS version of Mautic with premium features not available in Open Source.
  • For larger organizations, Mautic has a proprietary product called Maestro. Large organizations operate in many regions or territories, and have teams dedicated to each territory. With Maestro, each territory can get its own Mautic instance, but they can still share campaign best-practices, and repeat successful campaigns across territories. It's a unique capability, which is very aligned with the Acquia Cloud Site Factory.
Try Mautic

If you want to try Mautic, you can either install the community version yourself or check out the demo or sandbox environment of Mautic Open Marketing Cloud.

Conclusion

We're very excited to join forces with Mautic. It is such a strategic step for Acquia. Together we'll provide our customers with more freedom, faster innovation, and more flexibility. Open digital experiences are the way of the future.

I've got a lot more to share about the Mautic acquisition, how we plan to integrate Mautic in Acquia's solutions, how we could build bridges between the Drupal and Mautic community, how it impacts the marketplace, and more.

In time, I'll write more about these topics on this blog. In the meantime, please feel free to join DB Hurley, Mautic's founder and CTO, and me in a live Q&A session on Thursday, May 9 at 10am ET. We'll try to answer your questions about Acquia and Mautic.

Hook 42: Stanford Web Camp 2019

May 8, 2019 - 19:45
Stanford Web Camp 2019 Lindsey Gemmill Wed, 05/08/2019 - 12:45

Agiledrop.com Blog: Our blog posts from April 2019

May 8, 2019 - 16:13

In case you missed some of them, here’s an overview of our blog posts from April to get you up to speed. Enjoy!

READ MORE

Digitalist: New module: HTTP Status Code

May 8, 2019 - 14:25
HTTP Status Code is a new module to manipulate HTTP status header. HTTP Status Code is a new module to manipulate HTTP status header. Main reason for doing this module is that in some cases you need to do manual fixes on the server side to create 410 Gone headers for paths that you want to remove from Google search index, with this module active you could setup the paths directly in Drupal. You can find the the module at drupal.org. Normaly install should be done with composer - composer require drupal/http_status_code. The module supports all Headers used by Symfony\Component\HttpFoundation\Response - with that said - HTTP headers should be used with caution. So make sure what you understand the impact then you manipulate the HTTP Header - like adding a 301 Redirect Header will be real bad when you not have a redirect in place. If you remove a page, the request for the path of the page normally then gives a 404 not… Read More