"eval" blocked by CSP using on page-mod's contentScript - firefox-addon

Im trying to create an extension that will interacts with github.
I need to use "eval" in my code but im keep getting blocked by the page CSP.
This is a simplified version of my code:
const pageMod = require("sdk/page-mod").PageMod;
var contentScript = 'try {eval("console.log(\'hello from eval\')");} catch (e) {console.log("page mode " + e.message);}';
pageMod({
include: "*",
contentScript: contentScript ,
contentScriptWhen: "start"
});
Can someone help me solve the problem?

This because the Content Security Policy: https://developer.mozilla.org/en-US/docs/Security/CSP/CSP_policy_directives
Usually 99% of the time, the usage of eval can be replaced with something else. If you give the context (why you need the eval), we can try to suggest an alternative.
That's the easy way.
The hard way, is intercept the response from github, to remove that header, using the observer notification "http-on-examine-response", here there is a full example but you can probably have a simplified version of it.
Personally, I would try to avoid using eval, it's usually easier.

Related

How to load a Firefox addon on page load?

I'm using
chrome.tabs.onUpdated.addListener(function(){ });
on chrome, but it dos not work on Firefox, I have seen
browser.tabs.onUpdated.addListener(listener[, extraParameters])
on Firefox documentation, but I'm not sure how to use it, can someone give me an example?
chrome & browser API
You can use both chrome.* and browser.* API in Firefox.
chrome.* returns a callback function (although that is due to change to support Promise in manifest v3).
browser.* returns a Promise.
In case of *.addListene(), they always return a callback function.
Therefore, in Firefox the following are similar (and you can use either).
chrome.tabs.onUpdated.addListener(function(){
// do something
});
browser.tabs.onUpdated.addListener(function(){
// do something
});
browser.tabs.onUpdated.addListener() in Firefox can also have optional extraParameters but from your example it seems you might not need it.
ref:
chrome.tabs.onUpdated
browser.tabs.onUpdated

The getEntityAttributes() function in Thingsboard

I am trying to use the attributeService.getEntityAttributes function to obtain some server attributes of my device. I was using the .getEntityAttributesValues function when working with the 2.x version of Thingsboard and it was working fine. With the current version I am using the following code:
var conf = {
ignoreLoading: false,
ignoreErrors: true,
resendRequest: true
};
var myattr = attributeService.getEntityAttributes(entityID,'SERVER_SCOPE',["myattribute"],conf);
But I get no data or error back. I was using the .getEntityAttributesValues with .then() method but it doesn't seem to work anymore. It says ".then is not a function".
What am I doing wrong? Please help and tell me how to use the new function properly. I am using TB v.3.1.1 CE.
Thingsboard 2.x UI was made with AngularJS.
Thingsboard 3.x UI now uses Angular.
One of the key differences between these frameworks in regards of your problem is the move from Promise based services, to Observable based services.
Let's look at the source of the getEntityAttributes function:
https://github.com/thingsboard/thingsboard/blob/2488154d275bd8e6883baabba5519be78d6b088d/ui-ngx/src/app/core/http/attribute.service.ts
It's mostly a thin wrapper around a network call made with the http.get method from Angular.
Therefore, if we have a look at the official documentation: https://angular.io/guide/http#requesting-data-from-a-server, it is mentioned that we must subscribe to the observable in order to handle the response. So something along the lines of:
attributeService.getEntityAttributes(entityID,'SERVER_SCOPE',["myattribute"],conf).subscribe((attributes) => {…})

How can I make a firefox add-on contentscript inject and run a script before other page scripts?

I'm working on a Browser extension/add-on. We have it working in Chrome, so I'm trying to get it working in Firefox.
I've gotten my add-on to load in Firefox Developer Edition 49.0a2 (2016-07-25).
My extension involves a content_script set to run_at: document_start, so it can inject a script tag before other page scripts run, so it can make an object globally available to websites.
This has seemed to work fine in Chrome, but in Firefox it has proven to be a bit of a race condition, with other page resources loading first most of the time.
Is there a strategy to load a content script in a way that it can inject & load a script before any other page scripts run?
When I add logs, I can isolate what is happening pretty nicely. In this example content-script:
// inject in-page script
console.log('STEP 1, this always happens first')
var scriptTag = document.createElement('script')
scriptTag.src = chrome.extension.getURL('scripts/inpage.js')
scriptTag.onload = function () { this.parentNode.removeChild(this) }
var container = document.head || document.documentElement
// append as first child
container.insertBefore(scriptTag, container.children[0])
Now if the file scripts/inpage.js simply runs a log, like
console.log('STEP 2, this should always run second')
And I visit a page with a script like this:
console.log('Step 3, the page itself, should run last')
In practice, Step 2 and Step 3 run in a non-deterministic order.
Thanks a lot!
I have Firefox-compatible version of the script in a public repository on a special branch if you dare to try it yourself: https://github.com/MetaMask/metamask-plugin/tree/FirefoxCompatibility
An dynamically inserted script with an external source (<script src>) does not block the execution of scripts, so there is no guarantee that your script would load. If your extension worked in Chrome, it was just by sheer luck.
If you really want to run some script before the rest, you have to run it inline:
var actualCode = `
// Content of scripts/inpage.js here
`;
var s = document.createElement('script');
s.textContent = actualCode;
(document.head || document.documentElement).appendChild(s);
s.remove();
Ideally, your build script would read scripts/inpage.js, serialize it to a string and put it in the actualCode variable. But if inpage.js is just a few lines of code, then the above can be used.
Note that you should not inject code in the web page unless it is absolutely necessary. The reason for that is that the execution environment of the page is untrusted. If you inject at document_start, then you can save functions and (prototype) methods that use for later (in a closure), but very careful coding is required.
If your content script is not generated by a build script and you still want to keep the scripts separate, then you can also use synchronous XMLHttpRequest to fetch the script. Synchronous XHR is deprecated for performance reasons, so use it at your own risk. Extension code is typically bundled with your extension, so the use of sync xhr should be low-risk:
// Note: do not use synchronous XHR in production!
var x = new XMLHttpRequest();
x.open('GET', chrome.runtime.getURL('scripts/inpage.js'), false);
x.send();
var actualCode = x.responseText;
var s = document.createElement('script');
s.textContent = actualCode;
(document.head || document.documentElement).appendChild(s);
s.remove();
If you are using a bootstrap.js based addon you can use a framescript and DOMWindowCreated to work with the document before even the HTML DOM (past basics of document.body etc) renders - https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment#Events - the innerHTML will be available but no script would have executed. You can put your inline script at the top as #Rob mentioned.

Using Neo4j with React JS

Can we use graph database neo4j with react js? If not so is there any alternate option for including graph database in react JS?
Easily, all you need is neo4j-driver: https://www.npmjs.com/package/neo4j-driver
Here is the most simplistic usage:
neo4j.js
//import { v1 as neo4j } from 'neo4j-driver'
const neo4j = require('neo4j-driver').v1
const driver = neo4j.driver('bolt://localhost', neo4j.auth.basic('username', 'password'))
const session = driver.session()
session
.run(`
MATCH (n:Node)
RETURN n AS someName
`)
.then((results) => {
results.records.forEach((record) => console.log(record.get('someName')))
session.close()
driver.close()
})
It is best practice to close the session always after you get the data. It is inexpensive and lightweight.
It is best practice to only close the driver session once your program is done (like Mongo DB). You will see extreme errors if you close the driver at a bad time, which is incredibly important to note if you are beginner. You will see errors like 'connection to server closed', etc. In async code, for example, if you run a query and close the driver before the results are parsed, you will have a bad time.
You can see in my example that I close the driver after, but only to illustrate proper cleanup. If you run this code in a standalone JS file to test, you will see node.js hangs after the query and you need to press CTRL + C to exit. Adding driver.close() fixes that. Normally, the driver is not closed until the program exits/crashes, which is never in a Backend API, and not until the user logs out in the Frontend.
Knowing this now, you are off to a great start.
Remember, session.close() immediately every time, and be careful with the driver.close().
You could put this code in a React component or action creator easily and render the data.
You will find it no different than hooking up and working with Axios.
You can run statements in a transaction also, which is beneficial for writelocking affected nodes. You should research that thoroughly first, but transaction flow is like this:
const session = driver.session()
const tx = session.beginTransaction()
tx
.run(query)
.then(// same as normal)
.catch(// errors)
// the difference is you can chain multiple transactions:
const tx1 = await tx.run().then()
// use results
const tx2 = await tx.run().then()
// then, once you are ready to commit the changes:
if (results.good !== true) {
tx.rollback()
session.close()
throw error
}
await tx.commit()
session.close()
const finalResults = { tx1, tx2 }
return finalResults
// in my experience, you have to await tx.commit
// in async/await syntax conditions, otherwise it may not commit properly
// that operation is not instant
tl;dr;
Yes, you can!
You are mixing two different technologies together. Neo4j is graph database and React.js is framework for front-end.
You can connect to Neo4j from JavaScript - http://neo4j.com/developer/javascript/
Interesting topic. I am using the driver in a React App and recently experienced some issues. I am closing the session every time a lifecycle hook completes like in your example. When there where more intensive queries I would see a timeout error. Going back to my setup decided to experiment by closing the driver in some more expensive queries and it looks like (still need more testing) the crashes are gone.
If you are deploying a real-world application I would urge you to think about Authentication and Authorization when using a DB-React setup only as you would have to store username/password of the neo4j server in the client. I am looking into options of having the Neo4J server issuing a token and receiving it for Authorization but the best practice is for sure to have a Node.js server in the middle with something like Passport to handle Authentication.
So, all in all, maybe the best scenario is to only use the driver in Node and have the browser always communicating with the Node server using axios...

Can Breeze.js be optimized with r.js?

I have a SPA that makes use of the breeze.js library. I am using require.js to load modules. I want to optimize the application into a single JavaScript file using r.js, however I am getting the following error:
Tracing dependencies for: main
Error: ../Scripts/breeze.debug.js has two many anonymous modules in it.
at ...\Scripts\r.js:20154:35
Am I barking up the wrong tree trying to optimize with r.js? I can't see anything on the breeze.js site site to indicate that it can or can not be done.
Cut down version of m main.js:
require.config({
paths: {
"jquery": "../Scripts/jquery-1.9.1",
"Q": "../Scripts/q",
"breeze": "../Scripts/breeze.debug"
},
shim: {
"breeze": {
"deps": ["Q"]
}
},
});
require(["breeze"], function (breeze) {
//do something
});
Here is the app.build.js build file:
({
baseUrl: "../App",
mainConfigFile: '../app/main.js',
name: "main",
out: "../Build/Output/main-built.js"
})
Don't know why you're getting that error.
To be honest, we are unlikely to explore why any time soon mostly because we're not convinced that merging the entire application into a single file is a goal we would pursue with much enthusiasm.
There is great value in reducing the number of script files but it's not clear that there is much value in reducing that number to one. Breeze itself is on the (ahem) larger side so you've got a pretty healthy payload for that script request alone. A browser that can ask for scripts in parallel might actually load several scripts more quickly than it could load just one big script. And, finally, you could benefit from loading Breeze from a CDN rather than as embedded material in a mondo-script file on your web server.
Still, we hate the idea that this is failing for you. If you can figure out what is going on, we'd take reasonable steps to correct it. Thanks ... from the Breeze team.

Resources