安全な style アトリビュートのチェック案

HTML を無害化したいとき、style アトリビュートを問答無用に捨ててしまうのが主流なのだと思うのですけど、次のように HTML 用に記述内容を制限して利用可能にしたらどうだろうかと考えつつあります。
(2月7日 修正あり)
許可するもの:

  • IDENT を構成する文字をアルファベット・数字・マイナス・アンダースコアに限定
  • declaration は単位付き数値と keyword と hexcolor だけ
  • term 間はスペースとコンマとスラッシュだけ
  • スペースはブランク文字、タブ、LF、CRだけ

文字エスケープ、url、関数、文字列は不許可にします。
W3C の CSS2.1 の構文から、関連する部分を抜き出して上のルールに沿って不要なものを削ってみます。

http://www.w3.org/TR/CSS21/grammar.html

ruleset : S* declaration [ ';' S* declaration ]* ;
declaration : property ':' S* expr | ;
property : IDENT S* ;
expr : term [ operator term ]* ; /* 修正 */
operator : '/' S* | ',' S* | ;   /* 追加 */
term : ( unary_operator? NUMBER ('%'|IDENT)? | IDENT | hexcolor ) S* ;
unary_operator : '-' | '+' ;
IDENT : [_a-z][_a-z0-9-]* ;
NUMBER : [0-9]+|[0-9]*"."[0-9]+ ;
hexcolor : "#" [a-f0-9]+ ;
S : [\x20\t\r\n]

これを元にして、正規表現を作り、マッチングするかどうかをチェックする関数を書いてみると次のようになります。
(2月7日修正) property と keyword の正規表現を渡せるようにして、省略時はアルファベット列間をハイフンで繋いだものにマッチするようにしました。property は MSIE のアンダースコア・ハックも受け付けるようにしています。数値の単位も厳密にしました。さらに、font プロパティ等が使う、term 間のコンマとスラッシュのオペレータにマッチするようにしました。

sub is_safeStyle {
    my( $v, %arg ) = @_;
    my $PropertyRegexp = $arg{PropertyRegexp}
        || qr{[a-zA-Z]+(?:-[a-zA-Z]+)*};   # ADD
    my $KeywordRegexp = $arg{KeywordRegexp}
        || qr{[a-zA-Z]+(?:-[a-zA-Z]+)*};   # ADD
    my $term = qr{
        (?:[+-]?(?:\d+(?:\.\d+)?|\.\d+)
            (?i:\%|cm|deg|e[mx]|grad|Hz|in|kHz|m[ms]|p[ctx]|rad|s)? (?# MODIFY )
        |${KeywordRegexp}      (?# MODIFY )
        |\043[a-fA-F0-9]{1,6}
        )
        (?!-)\b                (?# ADD )
        [\x20\t\r\n]*
    }xo;  # ADD
    my $declaration = qr{
        (?: _?${PropertyRegexp}[\0x20\t\r\n]*  (?# MODIFY )
            :[\x20\t\r\n]*
            ${term}                            (?# MODIFY )
            (?:(?:[,/][\x20\t\r\n]*)?${term})* (?# ADD )
        )?
    }xo;
    $v !~ m{script:}i && $v =~ m{
        ^[\0x20\t\r\n]*${declaration}(?:;[\x20\t\r\n]*${declaration})*$
    }xo;
}

用心して、script: の文字列があるときは undef を返すようにしてみました。