Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
1

Question about localStorage.setItem(Key, Value) in extension

Participant ,
Jul 08, 2024 Jul 08, 2024

I wanted to ask how safe is to keep data inside localStorage.setItem(Key, Value).

If I want to create extension for Illustrator and want to store license key for that extension inside localStorage. License key in localStorage will be encrypted of course.

Is this safe to do such thing?

TOPICS
Scripting , SDK
1.4K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Enthusiast , Jul 19, 2024 Jul 19, 2024

It depends on what "safe" means. If you're including API keys to paid services then no, storing them in any local file or localStorage is not good practice and is very insecure even if encrypted, but if by "safe" you're asking if a malicious actor could harm the user in any way if they could access and decrypt your license key the short answer is no. At most, all that would happen is a lazily cracked version of your extension might be available online -- but if I wanted to do that, I'd just stri

...
Translate
Adobe
Participant ,
Jul 12, 2024 Jul 12, 2024

If someone enables debug mode, they will then be able to modify the script to do whatever they want, including access to all localStorage values.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 19, 2024 Jul 19, 2024

Yes but data will be encrypted.

Alternative is to store in some file but there also will be the case that data are accessible, but if they are encrypted we are on the same.

What is difference?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jul 19, 2024 Jul 19, 2024

It depends on what "safe" means. If you're including API keys to paid services then no, storing them in any local file or localStorage is not good practice and is very insecure even if encrypted, but if by "safe" you're asking if a malicious actor could harm the user in any way if they could access and decrypt your license key the short answer is no. At most, all that would happen is a lazily cracked version of your extension might be available online -- but if I wanted to do that, I'd just strip out the code in your extension that checks for licensing to begin with then resign and redistribute it as a ZXP to skip the licensing part entirely and unfortunately, no amount of security measures would prevent that due to how relaxed CEP is with self-signed certificates.

 

If I were a malicious actor looking to redistribute your extension with extra code that modifies the user filesystem then your manner of licensing is completely irrelevant regardless of the depth of your security measures from code visibility alone. All it would take is someone who knows what they're doing committing to the time and effort it would take to just erase whatever lines of code you're using to authenticate a license or make requests to bypass this issue, and though it's not an inevitably that's going to happen, taking too many steps trying to prevent it will end up being a sunken cost in my opinion. Either they have the skill (and you can't stop them anyway) or they don't, and either something like this will happen or it won't. Have decent SEO to appear above any redistribution on search engine results and that catches 99% of potential users finding that redistributed version to begin with. As someone who's made a variety of CEP extensions some of which for large clients with a combined userbase of over 20K licenses, it's never happened to mine, at least that I know of.

 

There are plenty of online resources about "API key provisioning" (exact phrase for ease of googling for you) that address and discuss this along with best practices for security, but it becomes a manner of scale and if I'm honest, I don't think any CEP extension merits the college education level of knowledge needed for perfect security. The Goldilocks Zone between simple and secure is something like this:

 

  • A handshake with an external broker like AWS Secrets Manager under a whitelisted domain/source, or in your case a License Manager with a very similar flow using "forward secrecy" concepts (key exchanges are based on temporary keys which lead to a sensitive key) -- your extension is the whitelisted source, the key is stored externally on the server of the manager, extension makes a request with some manner of token, if that request is validated correctly the manager sends the license key in request response, your extension now knows it's legitimately licensed via response. You'd be storing tokens in localStorage instead of license keys directly and can set these to expire after arbitrary lengths, but details on tokens themselves / how to generate or validate would depend on the specific manager or platform.
  • Using Proof Key for Code Exchange (PKCE) or equivalent in requests that require API access with paid rates when possible.

 

In my opinion, any obstacle is enough to discourage 90%. SHA-256 with some hidden salt could be plenty to store your license in localStorage since most likely will never get beyond that point. If it's your first extension or your first serious extension, it's hard not to have ideas like this -- "I want to prevent people from stealing my work", "I don't want to miss out on any paying customers" -- and so on, but the market is small and niche. Your target market are professional artists who are used to paying for SaaS solutions and other means of improving their production. Focusing too much on things like this can just be a distraction from a worried and anxious inner mind and in reality, won't make much meaningful difference unless your extension is successful enough to sell several hundreds or thousands of licenses to begin with. If the extension isn't 100% done in every other aspect, then there's more pressing work to attend to.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 25, 2024 Jul 25, 2024

@Inventsable Thank you for such detailed answer. I will select this as corect answer as I want to award for your time and for useful informations.

 

But I have one more question. It will be gumroad for license keys and unfortonelly store licence key locally.

Now, if for example I choose to store inside some file, license key and machine Id.

Lets say that this machine Id will protect against reuse this file on multiple computers, by simple coping file.

But still it will be possible to reuse this file in same computer, in the way that someone could just copy that file, do deactivation (which will be offer in extensions ui) and then just paste back that file.

What is the best protection against this?  

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jul 26, 2024 Jul 26, 2024

If I were doing it, I'd use fs.stat or fs.statsync to know when it was last modified:

 

// Use fs and path from node
const fs = require("fs");
const path = require("path");

// Resolve the filepath to absolute
const filePath = path.resolve("./somePathHere.json");

// Get the millisecond value of when the file was last modified:
const dateModified = fs.statSync(filePath).mtime.getTime();

 

If you're the one writing the file, write a key/value to localstorage with Date.now() at the same time your license file was written or whenever your panel is modifying it, then when the panel mounts in future compare if your localstorage value is equal to the license file stat getTime above within a small margin like ~20 ms (or just capture the getTime of the file after writing it for exact comparison). If it is equal you'll know that it was last modified by you, but if it isn't, the user (or something else) must have modified it.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 27, 2024 Jul 27, 2024

@Inventsable Thank you

Creation Time, Modification Time, Access Time....this is all possible to change with js or through terminal or some other app, right?
So is this then some protection?

 

He do not need to do any modification of file just need to do in this order: copy license file, deactivate, paste license file. And still will have functional extension on current computer and still one more actication as he just deactivate on that computer. And can do like this infinitely.

 

With that copy paste Creation Time of license file will change, but he can back to original value.
If I add that info about creation time in localstorage this will not protect from this above, right?

 

Please let me know if I did not understand you well?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jul 27, 2024 Jul 27, 2024
quote

Creation Time, Modification Time, Access Time....this is all possible to change with js or through terminal or some other app, right?

 

No, but even if they were, the user would need to be smart enough to open the panel with CEF Client to display localstorage values anyway. At the point they know how to do that, this is mostly a moot point, because like I originally posted there's nothing stopping someone from stripping out Javascript in your panel then resigning or using it as is, or even running arbitrary JS in the CEF console.

 

quote

He do not need to do any modification of file just need to do in this order: copy license file, deactivate, paste license file. And still will have functional extension on current computer and still one more actication as he just deactivate on that computer. And can do like this infinitely.

 

With that copy paste Creation Time of license file will change, but he can back to original value.
If I add that info about creation time in localstorage this will not protect from this above, right?

 

This is why I recommended and gave you date modified, not date created. Modified is changed whenever the file path changes or the content inside changes. Also you're using seating, so just poll the license and seats silently every 10 minutes and no one alive will have the patience to deactivate licenses manually like you've described 6 times per hour whenever they use the app.

 

I think you're massively over-thinking this. This is such an obscure use-case of how to "hack" and sure, if you can think of a hole you may as well try to fill it, but I cannot stress enough to you that there are much easier ways to bypass security and you are not going to be able to stop that. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 27, 2024 Jul 27, 2024

Why would they need to display localstorage values they can just read that data about time from license file itself.

I think that Modification Time is changed only when content of file is changed, not path and this behave is on win/mac the same. So only Creation Time of license file will change with copy/paste you can test that on some file.

 

But it does not matter, it could be that you though that file is present all the time (from time of extension installation), but it is created when it is activated and deleted after deactivation, maybe I did not explain that part.

Also I did not explain how gumroad works, it has verification of license key where you can choose to increase or not  increase number of uses on each verification. So I set  to increase only on activation (when user input lic. key for first time). That number of uses I am using to check agains max number of activation.

So I can check how many seats are busy only on activation so once he has license file he can use that without restriction.

 

 

"stripping out Javascript in your panel then resigning or using it as is, or even running arbitrary JS in the CEF console.  "  

"but I cannot stress enough to you that there are much easier ways to bypass security and you are not going to be able to stop that. "

For this part I do not know, obviously you have more expirence with security of cep extensions and not have reasons to not belive you.

I mean it is easy to copy and resign that part is obvious but how to access parts of js file which run functions from jsx (on both were applyied obfuscator) I did not have time to check yet. I am sure that there are workaround.    

I am very currious if you can not write here you are free to send me private message???

 

Sorry if I bored you, this was very interesting communication for me so far!

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jul 27, 2024 Jul 27, 2024
LATEST

You didn't specify that you were using Gumroad earlier, no. 

quote

I mean it is easy to copy and resign that part is obvious but how to access parts of js file which run functions from jsx (on both were applyied obfuscator) I did not have time to check yet. I am sure that there are workaround.    

 

Any obfuscation can be easily reversed (if you know what to look for or what libraries to use) and even JSXBIN has public cracks on Github allowing converting from JSXBIN back to human readable JSX so it's not secure either. This is the only point I'm trying to reiterate to you -- at some point this becomes a sunken cost. You're the one who decides when that point is, but genuinely I don't think it's something you have to worry or care about unless you know for a fact your extension is going to sell several hundreds if not thousands of licenses. The scope of CEP and the market existing inside it is just too small for nuanced license concerns, you're not pushing patches of CrowdStrike to millions of users here.

 

If you only sell 50 licenses with this product (which happens to every one, most of my own tools have not been as successful as I wanted them to be) then all this time, care, attention and worrying is for nothing but practice I guess.

 

But if someone knows how to use fs.utimesSync, then they likely already know how to reverse obfuscation or strip out your validation JS in the first place. All this "what if this" and "what if that" is just hyper-focusing on a very small and manual bypass that, in the big picture, is not very likely or even efficient in the first place. Say a user does deactivate then copy then reactivate, what does this produce? A single extra use per session of your tool requiring manual work every time in a way that can't be easily shared between several people? That's an extremely small problem to have.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines