stackblitz / core

Online IDE powered by Visual Studio Code ⚡️
https://stackblitz.com
MIT License
10.27k stars 898 forks source link

Secrets support #1492

Open nicholaschiang opened 3 years ago

nicholaschiang commented 3 years ago

Is your feature request related to a problem? Please describe.

I'd like to be able to specify API secrets in a StackBlitz project without sharing them publicly. I'm fine with the code being shared publicly (because the repository itself is open-source), but I don't want to have certain environment variables (e.g. API keys, secret tokens) shared publicly.

Describe the solution you'd like

I'd like to be able to specify secrets in a project's settings (that are only accessible via process.env when I'm logged in). Essentially, I just want StackBlitz to have CodeSandbox's existing secrets feature.

Describe alternatives you've considered

I could (if it's possible) create a private StackBlitz project and then just add the environment variables in a .env.local file.

Additional context

I'm trying to get Tutorbook working as a StackBlitz project so that I can edit on the go (via any web browser) wherever I am.

mwisnicki commented 3 years ago

There's an ugly workaround for frontend code - put them into localstorage of preview frame.

mwisnicki commented 3 years ago

And you can copy them into cookie to access them from node :)

FossPrime commented 2 years ago

And you can copy them into cookie to access them from node :)

@mwisnicki Do you have some sample node code for this? What you're proposing is extremely unusual... accessing browser LocalStorage from node.js

I'm unable to access LocalStorage from node as expected.

FossPrime commented 2 years ago

Has anyone made a secrets example in SB? Like a way to have a public sandbox that uses database passwords safely? I know this is not supported, @d3lm should we expect this in 2022, or should we workaround it now? Has anyone made an example of a Cookie based approach to storing secrets locally in a not to inconvenient way, one that shares the secret with the WC Node.js?

Also happy one year anniversary for this issue.

Codesandbox knocked this one off the park IMO, that was one of the few things I didn't complain about when I was using them: https://codesandbox.io/docs/secrets (They didn't even support Vite in sandboxes until I bugged them about it a few months ago)

mwisnicki commented 2 years ago

Unfortunately cookies seem to not work in StackBlitz so as an alternative I'm passing secrets explicitly to an api endpoint and then reload the page:

https://stackblitz.com/edit/node-secrets-example-localstorage?file=index.js

FossPrime commented 2 years ago

Unfortunately cookies seem to not work in StackBlitz so as an alternative I'm passing secrets explicitly to an api endpoint and then reload the page:

https://stackblitz.com/edit/node-secrets-example-localstorage?file=index.js

Wow, that is not what I would have done. My idea was to store the secrets in local storage and then pass them to the server with websockets or in url parameters in a fetch request.

Your idea is better, somehow... I have a strong feeling it can work... We just need to whitelist what cookies we allow and specify where to expect them from... Standby, Sandbox incoming

mwisnicki commented 2 years ago

You can also override fetch to always pass secrets in headers. Might be easier that way.

mwisnicki commented 2 years ago

Actually I think the cleanest solution would be something that works similar to login pages:

mwisnicki commented 2 years ago

Example code: https://stackblitz.com/edit/node-secrets-example-localstorage-v2?file=localStorageSecrets.js

FossPrime commented 2 years ago

https://stackblitz.com/edit/secrets-demo

I had a million ideas, only three work well enough right now.

These do not work:

For my uses, an ESM module that handles this would work fine. I always use Vite, so a vite plugin that stalls bootup until it receives secrets would be fine for me. Deleting secrets may need a cache clear. I'd also like the solution to work on incognito mode... which restricts cookies and serviceWorkers... but sessionstorage and localstorage seem to work fine. localstorage is sometimes unavailable for dumb reasons, like if safari is running in instagram.

Port based ideas or ones that run on a detached spawn have an issue of, how do we communicate the secret while maintaining Vavite/Vite HMR, when we don't have IPC. We could save them to a file like /tmp/secrets.json. That approach is obviously not very portable to baremetal. We could save them to a Vite loaded module like /tmp/secrets/CAT_API.ts, that would be ideal for HMR.

The best solution would be


Update from Discord's sylwiavargas

So .jshrc is the only file that is synced to localstorage (besides .jsh_history for the terminal history, but it should not be changed manually so let's ignore this one). But, it's across every single project. This means that if I add my secrets to .jshrc with export MY_SUPER_SECRET_GITHUB_TOKEN=1234, then my project can use process.env.MY_SUPER_SECRET_GITHUB_TOKEN . And it will still work after a refresh. This also means, that if you sent me a StackBlitz link you created, which reads the .jshrc from MY account, you can send it to your own server. So using secrets in .jshrc can be done, but you should be very careful. I always give them very limited access so if they leak, it doesn't really matter too much. And then you can remove them after you ran the project.

You can argue that using secrets in .jshrc is somewhat the same risk as doing that on local because you don't know what an npm install from a random github repo does on your machine but at the same time, it's easier to send a StackBlitz link to someone.

(this explanation came from the wonderful https://twitter.com/SamVerschueren who's generally great at explaining things if you're looking to follow some StackBlitz folks on

Twitter)

  1. This opens two other ideas... We can store base64 enoded secrets keyed by their project slug there
  2. We can hijack node and launch our own secrets server for every sandbox.

Not sure if this provides cross device sync... Developing

richpowell commented 2 years ago

Could an integration with doppler work for secrets management across sb? https://www.doppler.com/integrations

FossPrime commented 2 years ago

Could an integration with doppler work for secrets management across sb? https://www.doppler.com/integrations

StackBlitz has no such thing as a secure side and a public side. This makes Runkit, Code spaces, codesandbox or Kubernetes style secrets mathematically impossible.

There are two workarounds:

  1. Have secrets that are only seen and used by a handful of authorized users.
  2. Change what StackBlitz is fundamentally, and deploy sandboxes to something like Runkit with secrets in tow.
FossPrime commented 2 years ago

https://vitejs.dev/guide/api-plugin.html#client-server-communication

This is a new solution that could be really neat for projects that run vite.

The idea is to fetch localStorage keys beginning with secret-. If none are found and you have the plugin installed, overlay a form on screen to enter secrets. Once the secrets are loaded, they are passed as environment variables to import.meta.env.SECRETS

FossPrime commented 1 year ago

https://stackblitz.com/edit/vitejs-vite-itctul?file=package.json&terminal=m,y,%20,s,e,c,r,e,t,%20,m,e,s,s,a,g,e,dev

If you set your browser to forget site history... this might work. It's probably better than storing secrets in your sandbox. For secrets longer than 16 characters... it will take a while.

retrohacker commented 1 year ago

Popping on in to say I'm building a demo for a conference that uses the OpenAI API. I'd like for conference attendees to be able to use the project, but it currently requires setting env vars.

Having a way to configure and inject env vars into a StackBlitz project without sharing them would be a big win for this use case.

The feature would be a secret store that StackBlitz manages for a project per account instead of per project. When starting the project for the first time you'd be prompted to hydrate the secrets with your own values.

For some inspiration, Autocode has a decent approach to this: https://autocode.com