Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

fix: don't inline css in csp mode. #4411

Closed
wants to merge 1 commit into from
Closed

Conversation

tbosch
Copy link
Contributor

@tbosch tbosch commented Oct 14, 2013

Also add angular-csp.css to the resulting build.

@mary-poppins
Copy link

Thanks for the PR!

  • Contributor signed CLA now or in the past
    • If you just signed, leave a comment here with your real name
  • PR's commit messages follow the commit message format

If you need to make changes to your pull request, you can update the commit with git commit --amend.
Then, update the pull request with git push -f.

Thanks again for your help!

@@ -70,12 +71,17 @@ module.exports = {


addStyle: function(src, styles, minify){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change the addStyle function to this:

addStyle: function(src, styles, minify) {
    return styles.reduce(function(result, file) {
      var css = fs.readFileSync(file).toString();

      result.concatenatedCss += css + '\n';
      result.js += processCSS(css, minify);

      return result;
    }, {js: src, concatenatedCss: ''});

    function processCSS(css, minify) {
      // minify
      css = css
          .replace(/\r?\n/g, '')
          .replace(/\/\*.*?\*\//g, '')
          .replace(/:\s+/g, ':')
          .replace(/\s*\{\s*/g, '{')
          .replace(/\s*\}\s*/g, '}')
          .replace(/\s*\,\s*/g, ',')
          .replace(/\s*\;\s*/g, ';');

      // escape for JS
      css = css
        .replace(/\\/g, '\\\\')
        .replace(/'/g, "\\'")
        .replace(/\r?\n/g, '\\n');

      return "if (!document.securityPolicy || !document.securityPolicy.isActive) { angular.element(document).find('head').prepend('<style type=\"text/css\">" + css + "</style>'); }";
    }
  },

@vojtajina
Copy link
Contributor

LGTM

@tbosch
Copy link
Contributor Author

tbosch commented Oct 15, 2013

@vojtajina Thanks for the review.

Actually tested the condition document.securityPolicy in Firefox (24.0), Chrome (30.0) and Chrome Canary (32.0). And none of these seem to support it. To check, I uncommented util.csp() in the Gruntfile and created a dummy html file like this:

<!DOCTYPE html>
<html>
    <head>
        <script src="../build/angular.js"></script>
    </head>
</html>

This shows warnings in the javascript console regarding csp, and when I check document.securityPolicy manually it is undefined (also "securityPolicy" in document) returns undefined. If this does not work, the line in $sniffer also does not seem to work either...

@tbosch
Copy link
Contributor Author

tbosch commented Oct 15, 2013

Here is an idea for another solution, as checking document.securityPolicy is not working:

  • when using CSP, people have to add angular-csp.css (which contains the angular built-in styles for ngCloak, ...) manually before they add angular.js
  • angular.js checks if there are styles for ngCloak. If so, it does not add styles itself.
  • Otherwise, it tries to add the styles and checks if it succeeded. If not, it logs a nice error telling people that they are probably using CSP and that they should add the angular-csp.css manually before angular.js to their html file.

Integrating this with the ng-csp directive or $sniffer.csp property does not work as waiting until angular finished it's bootstrap is too late to add the styles to the document, specially for ngCloak.

@IgorMinar What do you think about this?

@IgorMinar
Copy link
Contributor

I created #4444 which fixes some of the issues also addressed in this PR. I think that we should merge #4444 first as it fixes a more general issue with CSP and then rebase this PR on top of master and get it in. The only colision should be in the grunt file which constructs the javascript string that injects the stylesheet.

@@ -91,7 +97,7 @@ module.exports = {
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(/\r?\n/g, '\\n');
return "angular.element(document).find('head').prepend('<style type=\"text/css\">" + css + "</style>');";
return "if (!document.securityPolicy || !document.securityPolicy.isActive) { angular.element(document).find('head').prepend('<style type=\"text/css\">" + css + "</style>'); }";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some changes that will make the changes on this line obsolte. see #4444

Also add `angular-csp.css` to the resulting build.
@tbosch
Copy link
Contributor Author

tbosch commented Oct 16, 2013

Refactored according to @vojtajina idea using reduce, a little differently though:

  addStyle: function(src, styles, minify){
    styles = styles.reduce(processCSS.bind(this), {
      js: [src],
      css: []
    });
    return {
      js: styles.js.join('\n'),
      css: styles.css.join('\n')
    };

    function processCSS(state, file) {
      var css = fs.readFileSync(file).toString(),
        js;
      state.css.push(css);

      if(minify){
        css = css
          .replace(/\r?\n/g, '')
          .replace(/\/\*.*?\*\//g, '')
          .replace(/:\s+/g, ':')
          .replace(/\s*\{\s*/g, '{')
          .replace(/\s*\}\s*/g, '}')
          .replace(/\s*\,\s*/g, ',')
          .replace(/\s*\;\s*/g, ';');
      }
      //escape for js
      js = css
        .replace(/\\/g, '\\\\')
        .replace(/'/g, "\\'")
        .replace(/\r?\n/g, '\\n');
      js = "if (!document.securityPolicy || !document.securityPolicy.isActive) { angular.element(document).find('head').prepend('<style type=\"text/css\">" + js + "</style>'); }";
      state.js.push(js);

      return state;
    }
  },

IgorMinar added a commit to IgorMinar/angular.js that referenced this pull request Oct 19, 2013
When we refactored , we broke the csp mode because the previous implementation
relied on the fact that it was ok to lazy initialize the .csp property, this
is not the case any more.

Besides, we need to know about csp mode during bootstrap and avoid injecting the
stylesheet when csp is active, so I refactored the code to fix both issues.

PR angular#4411 will follow up on this commit and add more improvements.

Closes angular#917
Closes angular#2963
Closes angular#4394
Closes angular#4444

BREAKING CHANGE: triggering ngCsp directive via `ng:csp` attribute is not
supported any more. Please use data-ng-csp instead.
IgorMinar added a commit that referenced this pull request Oct 19, 2013
When we refactored , we broke the csp mode because the previous implementation
relied on the fact that it was ok to lazy initialize the .csp property, this
is not the case any more.

Besides, we need to know about csp mode during bootstrap and avoid injecting the
stylesheet when csp is active, so I refactored the code to fix both issues.

PR #4411 will follow up on this commit and add more improvements.

Closes #917
Closes #2963
Closes #4394
Closes #4444

BREAKING CHANGE: triggering ngCsp directive via `ng:csp` attribute is not
supported any more. Please use data-ng-csp instead.
@IgorMinar
Copy link
Contributor

landed as a86cf20

@IgorMinar IgorMinar closed this Oct 22, 2013
jamesdaily pushed a commit to jamesdaily/angular.js that referenced this pull request Jan 27, 2014
When we refactored , we broke the csp mode because the previous implementation
relied on the fact that it was ok to lazy initialize the .csp property, this
is not the case any more.

Besides, we need to know about csp mode during bootstrap and avoid injecting the
stylesheet when csp is active, so I refactored the code to fix both issues.

PR angular#4411 will follow up on this commit and add more improvements.

Closes angular#917
Closes angular#2963
Closes angular#4394
Closes angular#4444

BREAKING CHANGE: triggering ngCsp directive via `ng:csp` attribute is not
supported any more. Please use data-ng-csp instead.
jamesdaily pushed a commit to jamesdaily/angular.js that referenced this pull request Jan 27, 2014
When we refactored , we broke the csp mode because the previous implementation
relied on the fact that it was ok to lazy initialize the .csp property, this
is not the case any more.

Besides, we need to know about csp mode during bootstrap and avoid injecting the
stylesheet when csp is active, so I refactored the code to fix both issues.

PR angular#4411 will follow up on this commit and add more improvements.

Closes angular#917
Closes angular#2963
Closes angular#4394
Closes angular#4444

BREAKING CHANGE: triggering ngCsp directive via `ng:csp` attribute is not
supported any more. Please use data-ng-csp instead.
@tbosch tbosch deleted the issue4394 branch February 6, 2014 19:23
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants