Skip to content

Instantly share code, notes, and snippets.

@theengineear
Created April 8, 2024 00:50
Show Gist options
  • Save theengineear/5d4a98bcaed6f1be38731b15fa49b52e to your computer and use it in GitHub Desktop.
Save theengineear/5d4a98bcaed6f1be38731b15fa49b52e to your computer and use it in GitHub Desktop.
Locked-down starting point for meta-injected Content Security Policy as a readable JavaScript file.
/**
* Injects CSP “meta” element into document head.
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
*
* Note, urls in "rules" blocks are alphabetized to make it easier to manage.
*
* Add as a “normal” (non-module) script to the document “<head>”. E.g.:
* <script src="/app-csp.js"></script>
*/
{
/**
* A CSP directive object.
*
* @typedef {{ name: string, rules: string[] }} CspDirective
*/
/**
* CSP fetch directives are used in a Content-Security-Policy header and
* control locations from which certain resource types may be loaded. For
* instance, script-src allows developers to allow trusted sources of script
* to execute on a page, while font-src controls the sources of web fonts.
*
* All fetch directives fall back to default-src. That means, if a fetch
* directive is absent in the CSP header, the user agent will look for the
* default-src directive.
*
* https://developer.mozilla.org/en-US/docs/Glossary/Fetch_directive
*
* @type {CspDirective[]}
*/
const fetchDirectives = [
{
/**
* Serves as a fallback for the other “fetch directives”.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src
*/
name: 'default-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for JavaScript and WebAssembly resources.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src
*/
name: 'script-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for JavaScript “<script>” elements. I.e., this
* determines what you can put in the “src” attribute on a “<script>” tag.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src-elem
*/
name: 'script-src-elem',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for JavaScript inline event handlers. I.e.,
* this determines whether and how you can set scripts for event handlers
* like “onclick” — ideally, this stays as 'none', use function handlers
* via “addEventListener”.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src-attr
*/
name: 'script-src-attr',
rules: [
'\'none\'',
],
},
{
/**
* Restricts the URLs which can be loaded using script interfaces.
* Importantly, this is what controls “fetch” API access.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src
*/
name: 'connect-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for stylesheets.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src
*/
name: 'style-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for stylesheets “<style>” elements and “<link>”
* elements with rel="stylesheet".
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src-elem
*/
name: 'style-src-elem',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for inline styles applied to individual
* DOM elements.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src-attr
*/
name: 'style-src-attr',
rules: [
'\'none\'',
],
},
{
/**
* Specifies valid sources of images and favicons.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/img-src
*/
name: 'img-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for fonts loaded using @font-face.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/font-src
*/
name: 'font-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for the <object> and <embed> elements.
*
* Note: Elements controlled by object-src are perhaps coincidentally
* considered legacy HTML elements and are not receiving new
* standardized features (such as the security attributes sandbox or
* allow for <iframe>). Therefor it is recommended to restrict this
* fetch-directive (e.g., explicitly set object-src 'none' if possible).
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/object-src
*/
name: 'object-src',
rules: [
'\'none\'',
],
},
{
/**
* Specifies valid sources for loading media using the <audio> , <video>
* and <track> elements.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/media-src
*/
name: 'media-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for nested browsing contexts loaded into
* elements such as <frame> and <iframe>.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-src
*/
name: 'frame-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources for Worker, SharedWorker, or
* ServiceWorker scripts.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/worker-src
*/
name: 'worker-src',
rules: [
'\'self\'',
],
},
{
/**
* Specifies valid sources of application manifest files.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/manifest-src
*/
name: 'manifest-src',
rules: [
'\'self\'',
],
},
/**
* The “child-src” directive is omitted. Use “frame-src” and “worker-src”.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/child-src
*/
];
/**
* Document directives govern the properties of a document or worker
* environment to which a policy applies.
*
* @type {CspDirective[]}
*/
const documentDirectives = [
{
/**
* Restricts the URLs which can be used in a document's “<base>” element.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/base-uri
*/
name: 'base-uri',
rules: [
'\'self\'',
],
},
/**
* The “sandbox” directive doesn’t work as “<meta>”. Omitted.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/sandbox
*/
];
/**
* Navigation directives govern to which locations a user can navigate or
* submit a form, for example.
*
* @type {CspDirective[]}
*/
const navigationDirectives = [
{
/**
* Restricts the URLs which can be used as the target of a form
* submissions from a given context.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/form-action
*/
name: 'form-action',
rules: [
'\'none\'',
],
},
/**
* The “frame-ancestors” directive doesn’t work as “<meta>”. Omitted.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors
*/
];
/**
* Reporting directives control the reporting process of CSP violations.
*
* @type {CspDirective[]}
*/
const reportingDirectives = [
{
/**
* Fires a SecurityPolicyViolationEvent.
*
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/report-to
*/
name: 'report-to',
rules: [],
},
];
const directives = [
...fetchDirectives,
...documentDirectives,
...navigationDirectives,
...reportingDirectives,
];
const meta = document.createElement('meta');
const content = `${directives.map(({ name, rules }) => `${name} ${rules.join(' ')}`).join('; ')};`;
meta.setAttribute('http-equiv', 'Content-Security-Policy');
meta.setAttribute('content', content);
document.currentScript.after(meta);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment