-
Notifications
You must be signed in to change notification settings - Fork 6
Isolate secrets from others extensions #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Isolate secrets from others extensions #13
Conversation
src/manager.ts
Outdated
throw new Error( | ||
`The secrets namespace ${namespace} is not available with the provided token` | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new Error( | |
`The secrets namespace ${namespace} is not available with the provided token` | |
); | |
Private.lock( | |
`The secrets namespace ${namespace} is not available with the provided token` | |
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't know if we want to lock the manager on any failing attempt. It should not occurs, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel strongly about this, but the only times I expect this to happen are in development so I erred on the side of security. I'm happy to defer to your judgement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could use a strict
flag that can be set when starting jupyterlab.
I am a little unsure about the |
(That doesn't need to be resolved in this PR, btw.) |
Co-authored-by: Afshin Taylor Darian <git@darian.link>
Thanks @brichet for working on it! |
The connector doesn't know the namespaces, it only associates an So yes, the unique connector should handle several namespaces. And actually the current design doesn't allow registering several connectors. |
So, how can I prevent an extension from fetching my AI provider secret key? I want only |
Ah I understand now. I can have logic inside my |
An extension can only use the manager to fetch a secret, it should not be able to use the connector directly. And the manager only allow signed in extension to fetch its namespace... |
src/manager.ts
Outdated
/** | ||
* Actually fetch the secret from the connector. | ||
*/ | ||
private async _get(id: string): Promise<ISecret | undefined> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also worried about this kind of method, that doesn't check the token.
This method is still available in javascript, even if private in typescript context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can move it into the Private namespace?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I can make them static and move them to the Private namespace.
I would suggest making a: get ready(): Promise<void> {
return this._ready.promise;
} And then in all the async methods, |
Also unless it's important not to, since |
It's already the case. Actually there are 2
|
Right, I see those promise delegates, I mean to not await the |
src/manager.ts
Outdated
const attachedId = Private.buildSecretId(namespace, id); | ||
Private.checkNamespace(token, namespace); | ||
const attachedId = Private.buildConnectorId(namespace, id); | ||
const attachedInput = this._attachedInputs.get(attachedId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_attachedInputs
should be in the private namespace, because i could do this in my extension
secretManager['_attachedInputs'].forEach(it => {
it.addeventlistener(...)
})
and get the value of the input when the secret value is filled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I realized that as well, but your extension can also do
document.querySelector('[data-namespace]')
And I don't think that we can do anything about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't have to save namespace and secret id to the input, just reverse the _attachedInputs map is enough to find these value from input element
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I agree that it would still be better to not expose it, but the extension can still do
document.querySelectorAll('input[type=password]')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, at this point we can't do anything
Thanks @afshin and @trungleduc for your helpful comments and suggestions. |
This PR aims to isolate the secrets from others extensions.
It includes two main ideas to prevent other extensions from recovering or defining secrets that don't belong to them.
Do not expose the
SecretsConnector
.Before this PR, the secrets connector was exposed by a token, that was consumed by the
SecretsManager
. This token could therefore be consumed by any other extension, which could fetch the secrets of a any namespace.With this PR, the secrets connector must be set to the secrets manager by the plugin itself. If several plugins try to set a connector, the manager is locked.
Allow only one extension per namespace (credit to @afshin for the idea and its implementation).
When a plugin want to use a namespace with the secrets manager, it has to 'sign in' and get a unique token. This token is required anytime the plugin needs to interact with the
SecretsConnector
(get
,set
,list
orremove
secrets).The secrets manager should be the only one able to access the
Map
objects that keep the relationship between the token and the namespace. To do so, it uses a private namespace that stores:Should fix #12
How to use it
If the token is used in an object, for privacy it should also use a
Private
namespace to be stored.cc. @afshin @jtpio @trungleduc