-
-
Notifications
You must be signed in to change notification settings - Fork 479
Fix attachment upload from custom widget with ACL #1512
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
Conversation
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.
Thanks @guillett. Some questions to help my understanding.
mreq.accessToken = token; | ||
// Once an accessToken is supplied, we don't consider anything else. | ||
// User is treated as anonymous apart from having an accessToken. | ||
mreq.user = user; |
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.
Is this safe? Could this potentially grant access to material beyond the specific document?
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 would say that, this is safe as long as the party with access to the provided token is trusted.
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.
Ok, I think I understand the concern you raise with that question. It may be possible to access (or update) a another document from a custom widget linked to a document with read (and write) access.
I have the feeling that if this fix "only" reinforce that vulnerability but it does not create it.
I looked at the existing test suite, I remember some related to access limitations but I can't remember if any exist on cross document access limitation/validation.
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.
Ok I tested this and I get a token misuse
from app/server/lib/Authorizer.ts
. Tested on DINUM sandbox environment and with the fix on my computer.
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.
Repository with tests https://github.com/guillett/test-grist-access/blob/main/pages/index.js
(Sorry I did not added a test in grist-core test suite)
this._pruneColumns(action, permInfo, tableId, accessCheck); | ||
} | ||
|
||
private async _checkAttachmentAccess(docSession: OptDocSession, attId: number) { |
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.
Can you talk me through what this fixes?
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.
It fixes one specific situation. When a file is not attached to any cell yet. Without this fix, the access is denied.
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.
Actually the lazy &&
does the same thing 😬
public async getAccessToken(docSession: OptDocSession, options: AccessTokenOptions): Promise<AccessTokenResult> { | ||
const tokens = this._server.getAccessTokens(); | ||
const userId = getUserId(docSession); | ||
const user = await this._granularAccess.getUser(docSession); |
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.
Can you walk me through what this fixes?
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.
It applied ACL related accessses instead of connected user's.
Also @guillett, I have just tried your reproduction scenario without success. I wondered if there exist steps that I should follow as the editor instead of the owner. |
@fflorent here a quick/fast 😅 demo |
@guillett thanks. I wonder if that's not due to the "view as" feature, simply. I'll try to reproduce that on my side. Also I see that you closed the issue, is it a missclick? |
Oh yes a missclick sorrryy |
@fflorent I confirm I have the issue when adding an editor (on another browser) and trying to sign and upload a file. |
Ah, I have made a mistake in my access rules. I know reproduce your issue @guillett! Also I could locate the code of your widget: https://github.com/betagouv/grist-previsionnel/blob/main/pages/signer-pdf.js |
494b5c5
to
872d599
Compare
@paulfitz we took a step back with @fflorent while reviewing this PR and came across this piece of code grist-core/app/server/lib/Authorizer.ts Lines 162 to 173 in b90a730
Reading the comment, it looks like the fact that providing an AccessToken does not identify the user is actually on purpose, we assume for security reasons ? Could you explain what motivates this ? Would it be an issue if a custom widget with an auth token could fully impersonate a user in a document through the REST API (@guillett has shown in a comment above that access is limited to the document) ? Trying to assert whether this limitation is by design or not, before looking at the best way to implement this 🙂 |
fwiw, @fflorent point out that the view-as helper defined here grist-core/app/common/DocListAPI.ts Lines 85 to 88 in b90a730
|
@guillett we think there's another workaround to your issue. Looking at your code (https://github.com/betagouv/grist-previsionnel/blob/80d573bbea25c8c27c6a672485da5bc81ea56d4a/pages/signer-pdf.js#L78-L98), you perform the attachment upload by the widget in 2 steps:
The fundamental issue is that, under "complicated access rules" context, Grist calls the We think there are two ways to solve this :
|
It could be reasonable for the AccessToken to identify the user. A naive implementation in that area of the code, though, would result in making the request have the full power and credentials of the user. That could have unintended consequences, for example, allowing other unrelated documents that the user has access to to be enumerated and read and modified for example. But the token is supposed to be narrower than that. Many ways to make this happen, some of them easy! The AccessToken work was a minimal piece of work needed to implement viewing attachments in a custom widget that happened to be somewhat more general purpose. But there wasn't time in the project to elaborate on it before moving on. I'd have loved to have built it out more. Sorry it is rough and ready! |
@paulfitz what's you take on this PR ? As far as we're concerned we're OK with the current implementation. Should we spend more time on this ? |
@guillett did you get a chance to try the workaround we suggested ? |
I tried but it failed, I got a I ended up adding a backend proxy with some level of check 😬 betagouv/grist-budget-agriculture@e37589f It is an ok temporary solution |
(and many many thanks for your time on this) |
@guillett @vviers I'd like to see this checked with non-doc endpoints such as |
Many thanks @paulfitz for your insights. You are right with the current implementation it drop existing protection. I will dig a little to suggest another implementation. |
Context
I am building a custom widget to sign PDF (not electronically, yet?) and I had issues when access rules apply.
Proposed solution
Fixing auth related bugs. 😬
Related issues
First of all, it was hard to get a minimal failing test.
To get a working bogus example
Has this been tested?
Screenshots / Screencasts