Content Security Policy: Feature Detection
AngularJS’s latest release candidate is the first
framework I’ve seen that cleanly supports a content security policy
that restricts usage of eval()
, new Function()
, and the like. I’m thrilled
to see this happening, and it’s a testament to the priority that the Angular
developers place on security. CSP is quite simply one the best XSS-protection
mechanisms available to developers these days in modern browsers. The more
frameworks that hop on board, the faster sites can start adopting CSP, and
the safer we’ll all be on the net.
All that said, the implementation isn’t as complete as it could be. Angular
requires that the developer manually opt into CSP-friendly mode via the
ng-csp
directive. This is error-prone at best, and introduces
complexity that would be better hidden away inside the framework. The Angular
developers recognize this shortfall, and are explicitly requesting
some sort of feature detection API that would allow frameworks to query the
currently active policy to determine its boundaries, and fork their
implementation accordingly.
This does seem like a great addition to the spec; I’d suggest the following implementation:
Add document.[prefix]contentSecurityPolicy
as an object that exists in
browsers that support CSP. This would enable trivial feature detection of CSP
as a whole, which would enable frameworks to make intelligent decisions about
how to proceed through the following use cases:
-
Is a policy enabled? If not, perhaps I’d like to set one via
meta
injection.document.contentSecurityPolicy.active
is a boolean property:true
if a policy is set,false
otherwise. -
Can I execute
eval()
or usenew Function()
?document.contentSecurityPolicy.isWhitelisted('script-src', 'unsafe-eval')
returnstrue
ifunsafe-eval
has been defined for thescript-src
directive. -
Can I embed a
data:
image or frame?document.contentSecurityPolicy.isWhitelisted('image-src', 'data:')
anddocument.contentSecurityPolicy.isWhitelisted('frame-src', 'data:')
-
Can I include Google Analytics?
document.contentSecurityPolicy.isWhitelisted('script-src', 'https://ssl.google-analytics.com')
(Note thatisWhitelisted
should do the hard work of dealing with wildcards. This example should returntrue
if*.google-analytics.com
is whitelisted.) -
Are reports being sent? If so, where are they going?
The
document.contentSecurityPolicy.reportUri
property is eitherundefined
if noreport-uri
directive is set, and a URI if the directive is set.
This seems like a reasonable first pass at a strawman for discussion. Thanks to Paul Irish, Eric Bidelman, and Pete LePage for walking through this with me.
What do you think?
— Mike West