diff --git a/deploy/csp/index.js b/deploy/csp/index.js
index 4ce347a10fbce23d2d50acd0ed02f1f4a3e9f9db..b37e4a7cdcf37dc918007d2c0fa0e3cbd64c66a2 100644
--- a/deploy/csp/index.js
+++ b/deploy/csp/index.js
@@ -1,15 +1,22 @@
 const csp = require('helmet-csp')
 const bodyParser = require('body-parser')
 
-let ALLOWED_DEFAULT_SRC, DATA_SRC
+let WHITE_LIST_SRC, DATA_SRC, SCRIPT_SRC
 
 const reportOnly = process.env.NODE_ENV !== 'production'
 
 try {
-  ALLOWED_DEFAULT_SRC = JSON.parse(process.env.ALLOWED_DEFAULT_SRC || '[]')
+  WHITE_LIST_SRC = JSON.parse(process.env.WHITE_LIST_SRC || '[]')
 } catch (e) {
-  console.warn(`parsing ALLOWED_DEFAULT_SRC error ${process.env.ALLOWED_DEFAULT_SRC}`, e)
-  ALLOWED_DEFAULT_SRC = []
+  console.warn(`parsing WHITE_LIST_SRC error ${process.env.WHITE_LIST_SRC}`, e)
+  WHITE_LIST_SRC = []
+}
+
+try {
+  SCRIPT_SRC = JSON.parse(process.env.SCRIPT_SRC || '[]')
+} catch (e) {
+  console.warn(`parsing SCRIPT_SRC error ${process.env.SCRIPT_SRC}`, e)
+  SCRIPT_SRC = []
 }
 
 try {
@@ -37,18 +44,24 @@ module.exports = (app) => {
   app.use(csp({
     directives: {
       defaultSrc: [
-        ...defaultAllowedSites
+        ...defaultAllowedSites,
+        ...WHITE_LIST_SRC
       ],
       styleSrc: [
         ...defaultAllowedSites,
         '*.bootstrapcdn.com',
         '*.fontawesome.com',
-        "'unsafe-inline'" // required for angular [style.xxx] bindings
+        "'unsafe-inline'", // required for angular [style.xxx] bindings
+        ...WHITE_LIST_SRC
+      ],
+      fontSrc: [
+        '*.fontawesome.com',
+        ...WHITE_LIST_SRC
       ],
-      fontSrc: [ '*.fontawesome.com' ],
       connectSrc: [
         ...defaultAllowedSites,
-        ...dataSource
+        ...dataSource,
+        ...WHITE_LIST_SRC
       ],
       scriptSrc:[
         "'self'",
@@ -59,7 +72,8 @@ module.exports = (app) => {
         'unpkg.com',
         '*.unpkg.com',
         '*.jsdelivr.net',
-        ...ALLOWED_DEFAULT_SRC
+        ...SCRIPT_SRC,
+        ...WHITE_LIST_SRC
       ],
       reportUri: '/report-violation'
     },
diff --git a/deploy/datasets/util.js b/deploy/datasets/util.js
index f8378038f74495fe3e0f4f01d69191a85932cbcf..284d85f89b424538cb45741d467e84a957dd38d7 100644
--- a/deploy/datasets/util.js
+++ b/deploy/datasets/util.js
@@ -36,13 +36,15 @@ const init = async () => {
 
 const retry = (fn) => {
   let retryId
-  retryId = setInterval(() => {
+  retryId = setTimeout(() => {
     fn()
       .then(() => {
         console.log(`retry succeeded, clearing retryId`)
         clearTimeout(retryId)
-      }).catch(e => {
+      })
+      .catch(e => {
         console.warn(`retry failed, retrying in 5sec`)
+        retry(fn)
       })
   }, 5000)
 }
diff --git a/src/atlasViewer/atlasViewer.pluginService.service.ts b/src/atlasViewer/atlasViewer.pluginService.service.ts
index 1b2aedcdb5969832c9b7b6fe68ca6e15693bf649..850a1c90aec004499c8ffe2512364ad8be847c2b 100644
--- a/src/atlasViewer/atlasViewer.pluginService.service.ts
+++ b/src/atlasViewer/atlasViewer.pluginService.service.ts
@@ -117,18 +117,12 @@ export class PluginServices{
 
   readyPlugin(plugin:PluginManifest):Promise<any>{
     return Promise.all([
-        isDefined(plugin.template) ?
-          Promise.resolve('template already provided') :
-          isDefined(plugin.templateURL) ?
-            this.fetch(plugin.templateURL, {responseType: 'text'})
-              .then(template=>plugin.template = template) :
-            Promise.reject('both template and templateURL are not defined') ,
-        isDefined(plugin.script) ?
-          Promise.resolve('script already provided') :
-          isDefined(plugin.scriptURL) ?
-            this.fetch(plugin.scriptURL, {responseType: 'text'})
-              .then(script=>plugin.script = script) :
-            Promise.reject('both script and scriptURL are not defined') 
+        isDefined(plugin.template)
+          ? Promise.resolve()
+          : isDefined(plugin.templateURL)
+            ? this.fetch(plugin.templateURL, {responseType: 'text'}).then(template=>plugin.template = template)
+            : Promise.reject('both template and templateURL are not defined') ,
+        isDefined(plugin.scriptURL) ? Promise.resolve() : Promise.reject(`inline script has been deprecated. use scriptURL instead`)
       ])
   }
 
@@ -239,7 +233,8 @@ export class PluginServices{
         }
 
         const script = document.createElement('script')
-        script.innerHTML = plugin.script
+        script.src = plugin.scriptURL
+
         this.appendSrc(script)
         handler.onShutdown(() => this.removeSrc(script))
 
diff --git a/src/atlasViewer/atlasViewer.urlService.service.ts b/src/atlasViewer/atlasViewer.urlService.service.ts
index a756f235b1cec42a20f7cbc2784eb2f8727eb300..ab2d36f759c6a595afb78cd4c2b0d896e7ccb2d6 100644
--- a/src/atlasViewer/atlasViewer.urlService.service.ts
+++ b/src/atlasViewer/atlasViewer.urlService.service.ts
@@ -179,6 +179,7 @@ export class AtlasViewerURLService{
                   /**
                    * TODO poisonsed encoded char, send error message
                    */
+                  this.uiService.showMessage(`cRegionSelectionParam is malformed: cannot decode ${n}`)
                   return null
                 }
               }).filter(v => !!v)
diff --git a/src/plugin_examples/README.md b/src/plugin_examples/README.md
index 2b1b126b3a0166eb2a416a5493705d5be63acd5e..c94e64a3d223507c0952d5115100b1c4d8f88ebc 100644
--- a/src/plugin_examples/README.md
+++ b/src/plugin_examples/README.md
@@ -6,7 +6,7 @@ A plugin needs to contain three files.
 - script JS
 
 
-These files need to be served by GET requests over HTTP with appropriate CORS header. If your application requires a backend, it is strongly recommended to host these three files with your backend. 
+These files need to be served by GET requests over HTTP with appropriate CORS header. 
 
 ---
 
@@ -109,5 +109,5 @@ The script will always be appended **after** the rendering of the template.
 - for every observable subscription, call *unsubscribe()* in the *onShutdown* callback
 - some frameworks such as *jquery2*, *jquery3*, *react/reactdom* and *webcomponents* can be loaded via *interactiveViewer.pluinControl.loadExternalLibraries([LIBRARY_NAME_1, LIBRARY_NAME_2])*. if the libraries are loaded, remember to hook *interactiveViewer.pluginControl.unloadExternalLibraries([LIBRARY_NAME_1,LIBRARY_NAME_2])* in the *onShutdown* callback
 - when/if using webcomponents, please be aware that the `connectedCallback()` and `disconnectedCallback()` will be called everytime user toggle between *floating* and *docked* modes. 
-- when user navigate to a new template all existing widgets will be destroyed, unless the `persistency` is set to `true` in `mannifest.json`.
+- when user navigate to a new template all existing widgets will be destroyed, unless the `persistency` is set to `true` in `manifest.json`.
 - for a list of APIs, see [plugin_api.md](plugin_api.md)