squidfunk / mkdocs-material

Documentation that simply works
https://squidfunk.github.io/mkdocs-material/
MIT License
20.86k stars 3.53k forks source link

Remove inline styles to avoid need for CSP style-src 'unsafe-inline' #858

Closed edmorley closed 5 years ago

edmorley commented 6 years ago

Description

Hi!

Currently mkdocs-material includes inline styles in the generated HTML, which means the insecure 'unsafe-inline' source has to be used for the style-src Content-Security-Policy (or else hashes manually generated, which is a pain).

Expected behavior

No inline styles.

Actual behavior

Inline styles in the generated HTML:

<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>

Which comes from: https://github.com/squidfunk/mkdocs-material/blob/7f08e2849a4d51ca7457e64bd2b2ab806103d771/src/base.html#L136-L145

...which result in the following errors in the browser console if the more secure style-src policy is used:

Content Security Policy: The page's settings blocked the loading of a resource at inline ("style-src").

Steps to reproduce the bug

  1. Generate a site using mkdocs 1.0.2 and mkdocs-material 3.0.3
  2. Serve the site with the following header set: Content-Security-Policy: style-src 'self' https://fonts.googleapis.com; (a reduced version of the actual policy that would be used on a production site)
  3. Visit the site in a modern CSP-supporting browser (in my case, today's Firefox Nightly)

Package versions

Project configuration

``` yaml docs_dir: 'docs' site_dir: 'build' strict: true site_name: 'Neutrino' site_description: 'Create and build modern JavaScript applications with zero initial configuration' repo_name: 'neutrinojs/neutrino' repo_url: 'https://github.com/neutrinojs/neutrino' # https://squidfunk.github.io/mkdocs-material/getting-started/#configuration theme: name: 'material' palette: primary: 'teal' accent: 'teal' # Disable the default top left logo until we sort out our custom one. logo: icon: ' ' # http://www.mkdocs.org/user-guide/writing-your-docs/#configure-pages-and-navigation nav: - Introduction: './index.md' - Getting Started: - Installation: './installation/index.md' - Create new project: './installation/create-new-project.md' - Usage: './usage.md' - Project Layout: './project-layout.md' - FAQ: './faq.md' - Learning Resources: './learning-resources.md' - CLI: './cli.md' - API: './api.md' - Configuration API - webpack-chain: './webpack-chain.md' - Customization: './customization.md' - Creating Presets: './creating-presets.md' - Migration Guide: './migration-guide.md' - Presets: './presets.md' - Middleware: './middleware.md' - Packages: - Web: './packages/web.md' - React: './packages/react.md' - Preact: './packages/preact.md' - Vue: './packages/vue.md' - Node.js: './packages/node.md' - Library: './packages/library.md' - React Components: './packages/react-components.md' - Airbnb: './packages/airbnb.md' - Airbnb Base: './packages/airbnb-base.md' - StandardJS: './packages/standardjs.md' - Karma: './packages/karma.md' - Mocha: './packages/mocha.md' - Jest: './packages/jest.md' - banner: './packages/banner.md' - clean: './packages/clean.md' - compile-loader: './packages/compile-loader.md' - copy: './packages/copy.md' - dev-server: './packages/dev-server.md' - eslint: './packages/eslint.md' - font-loader: './packages/font-loader.md' - html-loader: './packages/html-loader.md' - html-template: './packages/html-template.md' - image-loader: './packages/image-loader.md' - image-minify: './packages/image-minify.md' - loader-merge: './packages/loader-merge.md' - pwa: './packages/pwa.md' - start-server: './packages/start-server.md' - style-loader: './packages/style-loader.md' - style-minify: './packages/style-minify.md' - stylelint: './packages/stylelint.md' - v8 Documentation: 'https://neutrinojs.org/' - v7 Documentation: 'https://release-v7.neutrinojs.org/' - v6 Documentation: 'https://github.com/neutrinojs/neutrino/tree/release/v6/docs' - v5 Documentation: 'https://github.com/neutrinojs/neutrino/tree/release/v5/docs' - v4 Documentation: 'https://github.com/neutrinojs/neutrino/tree/release/v4/docs' - Contributing: - Overview: './contributing/index.md' - Development Process: './contributing/development.md' - Code of Conduct: './contributing/code-of-conduct.md' # https://squidfunk.github.io/mkdocs-material/getting-started/#extensions markdown_extensions: - admonition - codehilite: guess_lang: false - toc: permalink: true ```

System information

squidfunk commented 6 years ago

If we remove those inline styles, we'll lose the ability to easily change the font that is used for rendering. I understand that this violates CSP, but we cannot remove it as we would cripple functionality used by thousands of users. MkDocs (Jinja respectively) only allows HTML files for partials, so there's currently no other way (to my knowledge) to set the font.

edmorley commented 6 years ago

Hi! Thank you for the reply.

So i was looking at this a bit earlier, but forgot to comment. One way to solve this for the common case would be to only use inline CSS if people have overridden the chosen font (and set fonts via stylesheet otherwise). Users who want to customise the fonts and use CSP can then either:

...but at least people using default fonts won't have to have the complexity of either.

Thoughts?

squidfunk commented 6 years ago

There may need to be some other combinations we need to address. The default font should be Roboto if it isn't specified otherwise or font is set to false. Again, feel free to create a PR in which we can discuss concrete solutions how this can be implemented and I think we can make it into master. However, some documentation needs to be added on how to achieve maximum security and what options may impact it.

squidfunk commented 5 years ago

See https://github.com/squidfunk/mkdocs-material/issues/859#issuecomment-455127179