admin管理员组

文章数量:1305504

I'm allowing user-input css.

What is a light and performant way to validate that css on the client side?

I'm looking for a javascript solution. I don't want to send the css off to some remote server or anything.

Context: Allowing user css

Thanks.

Edit: NVM on this question. I started using a server-side validator:

I'm allowing user-input css.

What is a light and performant way to validate that css on the client side?

I'm looking for a javascript solution. I don't want to send the css off to some remote server or anything.

Context: Allowing user css

Thanks.

Edit: NVM on this question. I started using a server-side validator: https://github./chriso/node-validator

Share Improve this question edited May 23, 2017 at 10:34 CommunityBot 11 silver badge asked Jan 26, 2012 at 6:54 HarryHarry 55k76 gold badges185 silver badges270 bronze badges 3
  • 1 with node-validator, how to you validate that it's css content? – Honchar Denys Commented Dec 14, 2018 at 7:49
  • There is no way to validate CSS using the npm validator you linked to... – Augie Gardner Commented Jan 12, 2019 at 21:51
  • @HoncharDenys I only wanted to prevent XSS and not check for correctness. – Harry Commented Sep 13, 2022 at 1:47
Add a ment  | 

4 Answers 4

Reset to default 4

I think this is slightly safer than the @jcubic answer and will not cause the style to be applied to the current document:

function css_sanitize(css) {
    const iframe = document.createElement("iframe");
    iframe.style.display = "none";
    iframe.style.width = "10px"; //make small in case display:none fails
    iframe.style.height = "10px";
    document.body.appendChild(iframe);
    const style = iframe.contentDocument.createElement('style');
    style.innerHTML = css;
    iframe.contentDocument.head.appendChild(style);
    const sheet = style.sheet,
        result = Array.from(style.sheet.cssRules).map(rule => rule.cssText || '').join('\n');
    iframe.remove();
    return result;
}

You can use the CSSLint engine in your application. Its source is available at https://github./stubbornella/csslint

I've needed a way to prevent injection of html (which lead to XSS) code into my CSS editor. And I came up with this (using Native Browser DOM):

function css_sanitize(css) {
   var style = document.createElement('style');
   style.innerHTML = css;
   document.head.appendChild(style);
   var sheet = style.sheet;
   var result = Array.from(style.sheet.cssRules).map(rule => rule.cssText || '').join('\n');
   document.head.removeChild(style);
   return result;
}

Based on stringify-css-stylesheet, that actually have almost no code, the library split into two NPM packages have even less code.

Here is demonstration:

function css_sanitize(css) {
   var style = document.createElement('style');
   style.innerHTML = css;
   document.head.appendChild(style);
   var sheet = style.sheet;
   var result = Array.from(style.sheet.cssRules).map(rule => (rule.cssText || '')).join('\n');
   document.head.removeChild(style);
   return result;
}

var output = css_sanitize(`:root {
    --color: red;
    --options: {"enabled": false}; /* some JSON in CSS */
}
</style>
<script>alert('x')</` + `script>
<style>`);

console.log(output);

In my case the code was injected into <style>{{CSS}}</style> so when not protected the user could close style inject the script and open the style.

function getDefinedCss(s){
    if(!document.styleSheets) return '';
    if(typeof s== 'string') s= RegExp('\\b'+s+'\\b','i'); // IE capitalizes html selectors 

    var A, S, DS= document.styleSheets, n= DS.length, SA= [];
    while(n){
        S= DS[--n];
        A= (S.rules)? S.rules: S.cssRules;
        for(var i= 0, L= A.length; i<L; i++){
                tem= A[i].selectorText? [A[i].selectorText, A[i].style.cssText]: [A[i]+''];
                if(s.test(tem[0])) SA[SA.length]= tem;
        }
    }
    return SA.join('\n\n');
}

// Then you check the class if exists by calling getDefinedCss('myclassname')

本文标签: javascript validate cssStack Overflow