How to preform whitelist-based CSS filtering in PHP

心已入冬 提交于 2019-11-29 06:39:27

I guess you're going to write your own CSS parser and filter, so here's what I'd consider, although I've never done such a thing:

  • Make a (white) list of acceptable CSS properties that your users can use. Like: color, font-family.
  • I believe it might be better to not allow short-hand forms such as background, at least in the beginning, so that you can easily parse the values. Require that they explicitly write background-color, background-image.
  • If you want URLs, only allow relative URLs, and discard everything that doesn't even closely look like a URL. Log these issues anyway, so that you can improve your parser and validator.
  • Be very strict in your parsing, discard everything that your parser doesn't understand even if it would be valid CSS. In other words, make your own CSS subset.

When parsing, the hardest part would be the parsing of complex CSS selectors. But you can impose your own subset here too.

Here's some (pseudo)code, maybe it will help you somehow:

<?php

function tokenizeCSS() {
    return array(
        array(
            'selector'   => '#foo .bar',
            'properties' => array(
                'background-color' => 'transparent',
                'color'            => '#fff',
            ),
        );
    );
}

function colorValidator($color)
{}

/**
 * This is basically the white list. Keys are accepted CSS properties
 * and values are the validator callbacks.
 */
$propertyValidators = array(
    'background-color' => 'colorValidator',
    'color'            => 'colorValidator',
);

$filteredRules = array();

foreach (tokenizeCSS() as $rule) {
    if (! validSelector($rule['selector'])) {
        continue;
    }

    foreach ($rule['properties'] as $property => $value) {
        /**
         * Check property is in white list
         */
        if (! isset($propertyValidators[$property]) {
            continue;
        }

        /**
         * Check property is valid
         */
        if (! $propertyValidators[$property]($value)) {
            continue;
        }

        /**
         * Valid rule
         */
        $filteredRules[$rule['selector']][$property] = $value;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!