Helmet blocking bootstrap - express

At first, bootstrap didn't load, so I put this:
app.use(helmet());
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.jsdelivr.net"],
objectSrc: ["'none'"],
styleSrc: ["'self'", "https://cdn.jsdelivr.net"],
fontSrc: ["https://fonts.gstatic.com"],
upgradeInsecureRequests: [],
},
})
);
Then this bug comes in: "Refused to load the font 'data:font/truetype;charset=utf-8;base64,AAEAAAAQAQAABAAARkZUTX2Nv5YAAjnoAAAAHEdERUYENABTAAHJmAAAACRHUE9T4BjvnAACObAAAAA2R1NVQgmn+v0AAcm8AABv9E9TLzIKcyJjAAABiAAAAGBjbWFwv7oVNQAACfQAAAYWY3Z0IAARAUQAABAMAAAABGdhc3D//wADAAHJkAAAAAhnbHlmCJ88vQAAGBgAAYfUaGVhZAkc3WMAAAEMAAAANmhoZWEEAQIFAAABRAAAACRobXR4diRu0wAAAegAAAgMbG9jYdlVdhQAABAQAAAIBm1heHAEXADhAAABaAAAACBuYW1ludepWgABn+wAAAKdcG9zdBJ+3qAAAaKMAAAnBAABAAAAAQPX5ykXUl8PPPUAHwIAAAAAANP0zEUAAAAA0/TMSAAA//4CAAIEAAAACAACAAAAAAAAAAEAAAIAAAAAAAIAAAAAAAIAAAEAAAAAAAAAAAA...4AIAAgABIAIQIoAAgADwANACAAIgAbABsAJgL2AAgAFQAOACEAIAAVABwAIQIlAAcADwANAA4AIgAhABwA2gAHABIAEgAYABIAGwARAQIABwAWABEAFAASACEAIAAqAAcADgAfABsAFgAbABQBkwAFAA4AIQAQABUDqwAEABwAHwAYAtEABAAWABMAFgBdAAMAEgAPAtAAAgAQAAEABAOsABQAHAAiACEAIgAPABIADQAgABIADgAfABAAFQASABEADQATABwAHwADAAgAIgA0AnMADAAcABwAGgANABwAIgAhAA0AGgAOAB0DsgAIABwAHAAaAA0AHAAiACEDsQAHABwAHAAaAA0AFgAbAAIABAAGAAcAAAAOABYAAgAYACQACwAmACcAGAABAAAACgAeADQAAWxhdG4ACAAEAAAAAP//AAEAAAABc2l6ZQAIAAQAAACgAAAAAAAAAAAAAAAAAAAAAQAAAADVpCcIAAAAANP0zEUAAAAA0/TMSA=='"
How can I fix that?

You have to use contentSecurityPolicy. For example if you have used these CDN links for loading bootstrap:
doctype html
html
head
title D&C
link(href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta1/dist/css/bootstrap.min.css", rel="stylesheet", integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1", crossorigin="anonymous")
style
include ./styles.css
body
include nav
block content
block footer
footer
//- p © #{new Date().getFullYear()}
script(src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4", crossorigin="anonymous")
script(src="https://cdn.jsdelivr.net/npm/#popperjs/core#2.11.6/dist/umd/popper.min.js" integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3", crossorigin="anonymous")
Solution 1: set contentSecurityPolicy to false
// This disables the `contentSecurityPolicy` middleware but keeps the rest.
app.use(
helmet({
contentSecurityPolicy: false,
})
);
Solution 2: Configure contentSecurityPolicy
// app.use(helmet());
app.use(
helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "cdn.jsdelivr.net"],
styleSrc: ["'self'", "cdn.jsdelivr.net"],
},
})
);

Try adding a trailing slash, like this:
"https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/"
instead of
​"https://cdn.jsdelivr.net"
This is because "https://cdn.jsdelivr.net" doesn’t let you do things like "https://cdn.jsdelivr.net/npm/bootstrap#5.1.3/dist/css/bootstrap.min.css", but adding the trailing "/" does. This is a Content Security Policy thing, not a Helmet thing.
Answered by the author of Helmet here

Related

VueJS, displaying static images vs. binding a function from methods [duplicate]

I'm looking for the right url to reference static assets, like images within Vue javascript.
For example, I'm creating a leaflet marker using a custom icon image, and I've tried several urls, but they all return a 404 (Not Found):
Main.vue:
var icon = L.icon({
iconUrl: './assets/img.png',
iconSize: [25, 25],
iconAnchor: [12, 12]
});
I've tried putting the images in the assets folder and the static folder with no luck. Do I have to tell vue to load those images somehow?
For anyone looking to refer images from template, You can refer images directly using '#'
Example:
<img src="#/assets/images/home.png"/>
In a Vue regular setup, /assets is not served.
The images become src="data:image/png;base64,iVBORw0K...YII=" strings, instead.
Using from within JavaScript: require()
To get the images from JS code, use require('../assets.myImage.png'). The path must be relative (see below).
So your code would be:
var icon = L.icon({
iconUrl: require('./assets/img.png'), // was iconUrl: './assets/img.png',
// iconUrl: require('#/assets/img.png'), // use # as alternative, depending on the path
// ...
});
Use relative path
For example, say you have the following folder structure:
- src
+- assets
- myImage.png
+- components
- MyComponent.vue
If you want to reference the image in MyComponent.vue, the path sould be ../assets/myImage.png
Here's a DEMO CODESANDBOX showing it in action.
A better solution would be
Adding some good practices and safity to #acdcjunior's answer, to use # instead of ./
In JavaScript
require("#/assets/images/user-img-placeholder.png")
In JSX Template
<img src="#/assets/images/user-img-placeholder.png"/>
using # points to the src directory.
using ~ points to the project root, which makes it easier to access the node_modules and other root level resources
In order for Webpack to return the correct asset paths, you need to use require('./relative/path/to/file.jpg'), which will get processed by file-loader and returns the resolved URL.
computed: {
iconUrl () {
return require('./assets/img.png')
// The path could be '../assets/img.png', etc., which depends on where your vue file is
}
}
See VueJS templates - Handling Static Assets
Right after oppening script tag just add import someImage from '../assets/someImage.png'
and use it for an icon url iconUrl: someImage
this finally worked for me, image passed as prop:
<img :src="require(`../../assets/${image}.svg`)">
What system are you using? Webpack? Vue-loader?
I'll only brainstorming here...
Because .png is not a JavaScript file, you will need to configure Webpack to use file-loader or url-loader to handle them. The project scaffolded with vue-cli has also configured this for you.
You can take a look at webpack.conf.js in order to see if it's well configured like
...
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
...
/assets is for files that are handles by webpack during bundling - for that, they have to be referenced somewhere in your javascript code.
Other assets can be put in /static, the content of this folder will be copied to /dist later as-is.
I recommend you to try to change:
iconUrl: './assets/img.png'
to
iconUrl: './dist/img.png'
You can read the official documentation here: https://vue-loader.vuejs.org/en/configurations/asset-url.html
Hope it helps to you!
It works for me by using require syntax like this:
$('.eventSlick').slick({
dots: true,
slidesToShow: 3,
slidesToScroll: 1,
autoplay: false,
autoplaySpeed: 2000,
arrows: true,
draggable: false,
prevArrow: '<button type="button" data-role="none" class="slick-prev"><img src="' + require("#/assets/img/icon/Arrow_Left.svg")+'"></button>',
Having a default structure of folders generated by Vue CLI such as src/assets you can place your image there and refer this from HTML as follows <img src="../src/assets/img/logo.png"> as well (works automatically without any changes on deployment too).
I'm using typescript with vue, but this is how I went about it
<template><div><img :src="MyImage" /></div></template>
<script lang="ts">
import { Vue } from 'vue-property-decorator';
export default class MyPage extends Vue {
MyImage = "../assets/images/myImage.png";
}
</script>
You could define the assets path depending on your environment
const dev = process.env.NODE_ENV != 'production';
const url = 'https://your-site.com';
const assets = dev ? '' : url;
<template>
<img :src="`${assets}/logo.png`"/>
<p>path: {{assets}}</p>
</template>
<script>
export default {
data: () => ({
assets
})
}
</script>
Ideally this would be inside an utils js file, or as an extended app defineProperty, like:
const app = createApp(component);
app.config.globalProperties.$assets = assets;
app.mount(element);
and will be available as:
<template>
<img :src="`${$assets}/logo.png`"/>
<p>path: {{$assets}}</p>
</template>
<script>
export default {
mounted() {
console.log(this.$assets);
}
}
</script>
load them in created, mounted or where you need them
async created() {
try {
this.icon = (await import('#assets/images/img.png')).default;
} catch (e) {
// explicitly ignored
}
and then
<img :src=icon />
Inside code you can directly require image using.
const src = require("../../assets/images/xyz.png");
Or
In order to dynamically load image need this.
const image = new window.Image();
image.src = require("../../assets/images/xyz.png");
image.onload = () => {
// do something if needed
};

Workbox cache not used by <img /> tag

Setup
"workbox-cdn": "^5.1.4",
"nuxt": "^2.15.2"
Context
My app, Pictalk, let users save and get pictograms. So basically every user has a custom set of pictograms. For now, it works only online but I want to implement offline-mode.
Technical Details
I display all my pictograms with the html <img .../> tag.
Every time I load a new pictogram I do so:
created(){
if(navigator.onLine){
caches.open('pictos').then((cache) => {
cache.add(this.collection.path)
.then(() => {})
.catch((err)=> {console.log(err)})
});
}
},
Here is a screenshot of the Cache Storage :
As we see the URL is correct and the requests are cached correctly.
Problem
The <img .../> tag doesn't use the workbox cache I created.
Found out the solution here and here.
Here is the files I had to modify in order to make it work :
First, my <img/> tags had to use the crossorigin="anonymous" method :
<img class="image" style :src="path" crossorigin="anonymous"/>
Once the <img/> tags are more flexible with their origin we can start building our custom registered workbox route:
// plugins/workboxConfig.js
workbox.routing.registerRoute(
new RegExp('https://myapi\\.somewhere\\.com/pictalk/image/.*\\.(png|jpg|jpeg)'),
new workbox.strategies.CacheFirst({
cacheName: 'pictos',
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [200] }),
new workbox.rangeRequests.RangeRequestsPlugin(),
],
matchOptions: {
ignoreSearch: true,
ignoreVary: true
}
}),
);
I had to declare this file here in the nuxtjs.config.js :
pwa: {
workbox: {
cachingExtensions: '#/plugins/workboxConfig.js'
}
}

Using <object> to embed svg but doesn't show anything

I was trying to use to embed the svg picture but it does not show anything. I looked at some other threads and it was suggested to add type="image/svg+xml", however, it did not solve the issue. When I am trying to look at the DOM for some reason it seems to create an endless loop. I attached the picture
This is the compononent
<template>
<div class="logo">
<object type="image/svg+xml" data="logo.svg">
</object>
</div>
</template>
This is the app.vue
template>
<div id="app">
<Demo></Demo>
</div>
</template>
<script>
import Demo from './components/Demo.vue'
export default {
name: 'app',
components: {
Demo
}
}
</script>
```[![Snapshot][1]][1]
[1]: https://i.stack.imgur.com/Q6ipO.png
This happen because vue-loader doesn’t recognize paths in just any attribute. By default just recognize these ones: https://vue-loader.vuejs.org/options.html#transformasseturls
So, there are 3 possible solutions
Note: If you are not using eslint as linter you could remove eslint comments
1: Bind the route to your image
First add the next variable to your data in the component
data() {
return {
// eslint-disable-next-line global-require
mySvg: require('../assets/logo.svg'),
};
},
Next modify your template
<object type="image/svg+xml" :data="mySvg">
2: Add vue-loader rule
If you don't want to have to bind every svg image, you could add a rule to vue-loader in order to say how to handle data attribute in a object
Go to your webpack config file, if you created the project using vue-cli 3.x you have to create a vue.config.js file in the root (same level that package.json)
// vue.config.js
module.exports = {
chainWebpack: (config) => {
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap((options) => {
// eslint-disable-next-line no-param-reassign
options.transformAssetUrls = {
object: 'data',
};
return options;
});
},
};
if you want to check that the config was added, execute vue inspect > webpack.config and expect see something like this (inside webpack.config):
{
loader: 'vue-loader',
options: {
...
transformAssetUrls: {
object: 'data'
}
}
}
More info: https://cli.vuejs.org/guide/webpack.html#working-with-webpack
3: Replace default loader and use svg as vue components
Other option is use vue-svg-loader. This loader inlines the SVGs which enables you to modify them using css. Also optimize your files with SVGO
See more: https://vue-svg-loader.js.org/#vue-cli
It is worth checking that you don't have a CSS rule hiding object tags. Otherwise it seems correct. You probably need to check the path and make sure you can reach your image. I assume your filename is a dummy, but try to use an absolute path. And make sure you can hit the path and see the image in your browser.

Custom print style with Vue.JS print plugin

I am trying to print a VueJS component with custom print style.
Three Vue plugins look interesting on this subject:
1.printd
2.vue-print-nb
3.html-to-paper
Out of the three only html-to-paper has a options object that can pass a custom css style in order to dynamically pass some print css.
My issue is that i can't seem to load the custom css, and also bootstrap classes are messed up on print action.
This is basically what i am doing.
import VueHtmlToPaper from 'vue-html-to-paper'
const options = {
name: '_blank',
specs: [
'fullscreen=yes',
'titlebar=yes',
'scrollbars=no'
],
styles: [
'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css',
'./myPrint.css'
]
}
Vue.use(VueHtmlToPaper, options)
Any suggestion is welcomed.
Thanks
I have tried all these three I think the best one is print.js which is not specifically for Vue.js but it is easily install-able and usable in the vue components.
For example
<script>
import print from "print-js";
export default {
methods: {
printing() {
const style =
"#page { margin-top: 400px } #media print { h1 { color: blue } }";
const headerStyle = "font-weight: 300;";
printJS({
printable: "rrr",
type: "html",
header: "Doctor Name",
headerStyle: headerStyle,
style: style,
scanStyles: false,
onPrintDialogClose: () => console.log("The print dialog was closed"),
onError: e => console.log(e)
});
},
printVisit(id) {
this.$htmlToPaper("rrr");
this.$htmlToPaper("rrr", () => {
console.log("Printing completed or was cancelled!");
});
}
}
};
</script>
VueHtmlToPaper opens a new window with its own style tag. So when you pass a CDN it works, if u pass a local file it does not because it tries to access the resource in your web server but in the wrong URL. Let's see how the page looks when we use a CDN and a local CSS file.
CDN
<html>
<head>
<link rel="style" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css">
</head>
<body>
</body>
</html>
Local CSS file
And let's say you are calling the print function from http://localhost:8080/somepage
<html>
<head>
<link rel="style" href="./myPrint.css">
</head>
<body>
</body>
</html>
This will try to open http://localhost:8080/somepage/myPrint.css. Obviously this will not be accessible to print dialogue.
Solution
Put your custom CSS file in the public or static folder (Where you usually keep favicon)
Modify script path in options, prepend server basepath with the CSS file
Sample Option
import VueHtmlToPaper from 'vue-html-to-paper'
/* This will change according to your server */
let basePath= 'http://localhost:8080';
const options = {
name: '_blank',
specs: [
'fullscreen=yes',
'titlebar=yes',
'scrollbars=no'
],
styles: [
'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css',
`${basePath}/myPrint.css`
]
}
Vue.use(VueHtmlToPaper, options)
Also, the simplest way to access root-relative path is to use /. User /style.css instead of ./style.css

Dojo amd loading cross-domain modules at runtime

I want to load Dojo1.9 amd modules from an ad-hoc server on the www, but I won't know from where until runtime (with url params).
In essence, I want to do the equivalent of this:
require(['http://www.foo.com/SomeRandomModule'], function( SomeRandomModule ) {
// use SomeRandomModule
});
Quick and dirty way
Might have some unexpected quirks when it comes to the module system and relative paths, I haven't used it enough to say:
require([ "//host/myext/mod1/mod2.js" ],function(mod2){
// If current webpage is http:// or https:// or file://
// it tries to use the same protocol
});
Better way
Configure require() to treat all modules that start with a certain package name (e.g. foo) as coming from a particular URL. From your starter page, something like:
<script src="dojo/dojo.js"
data-dojo-config="packages:[{name:'myext',location:'//host/js/myext'}], async: 1, >
</script>
This lets you vastly improve your first example to:
require([ "myext/mod1/mod2" ],function(mod2){
});
If you are using a Dojo Bootstrap installation instead, you can avoid touching your data-dojo-config and instead put it inside the run.js startup file:
require({
baseUrl: '',
packages: [
'dojo',
'dijit',
'dojox',
'myapp',
{ name: 'myext', location: '//host/js/myext', map: {} }
]
}, [ 'myapp' ]);