Skip to content

Scope laboratory assay protocol lookups to the request container#286

Open
labkey-martyp wants to merge 2 commits into
release25.7-SNAPSHOTfrom
25.7_fb_laboratory_protocol_scope
Open

Scope laboratory assay protocol lookups to the request container#286
labkey-martyp wants to merge 2 commits into
release25.7-SNAPSHOTfrom
25.7_fb_laboratory_protocol_scope

Conversation

@labkey-martyp

Copy link
Copy Markdown

Rationale

GetImportMethodsAction and four sibling actions in LaboratoryController looked up assay protocols by row id via ExperimentService.getExpProtocol(int), an unscoped global primary-key lookup. Because these actions are guarded only by container-level permissions, a user with read access to any single folder could supply an arbitrary protocol row id and have the server operate on a protocol defined in a folder they cannot read. GetImportMethodsAction additionally echoed the protocol's name, container, and container path back in its response, allowing cross-container enumeration of assay design names and folder paths (an IDOR / information-disclosure issue). The unchecked lookup in GetImportMethodsAction could also NPE on a non-existent row id.

Related Pull Requests

None.

Changes

  • Each protocol lookup now verifies the protocol is in scope for the request container via AssayService.getAssayProtocols(getContainer()) before use, covering GetImportMethodsAction, ProcessAssayDataAction, SaveTemplateAction, CreateTemplateAction, and GetAssayImportHeadersAction.
  • The scope check is folded into each existing null guard, returning the same generic not-found message whether the row id is unknown or simply out of scope, so the response is not an existence oracle.
  • Legitimate same-container callers (e.g. Laboratory.Utils.getAssayDetails from the assay import/template panels) are unaffected, since they always pass an in-scope protocol.

GetImportMethodsAction and four sibling actions in LaboratoryController looked up assay protocols by row id via ExperimentService.getExpProtocol(int), an unscoped global primary-key lookup. Because the actions are guarded only by container-level permissions, a user with read access to any single folder could pass an arbitrary row id and have the server use — and, in GetImportMethodsAction, echo back the name, container, and container path of — a protocol defined in a folder they cannot read, enabling cross-container enumeration of assay designs and folder paths.

Each lookup now verifies the protocol is in scope for the request container via AssayService.getAssayProtocols(getContainer()) before use, returning the same generic not-found message whether the row id is unknown or simply out of scope so the response is not an existence oracle. Legitimate same-container callers are unaffected.
@labkey-martyp labkey-martyp requested a review from bbimber June 18, 2026 21:57
@bbimber

bbimber commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Hi @labkey-martyp, do you know how assays defined in the shared container are treated under this change?

@bbimber

bbimber commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Also, just curious, is the recent set of permission related PRs AI driven?

@labkey-martyp

labkey-martyp commented Jun 18, 2026

Copy link
Copy Markdown
Author

@bbimber there should be no change in behavior for assays in the Shared folder. They would be considered in-scope for the current folder. AssayService.get().getAssayProtocols(getContainer()) will include /Shared.

@labkey-martyp

Copy link
Copy Markdown
Author

Also, just curious, is the recent set of permission related PRs AI driven?

Yes we are using AI to do scans for potential security issues. I anticipate there will be communication on that once we've patched any issues.

@labkey-martyp

Copy link
Copy Markdown
Author

Also, just curious, is the recent set of permission related PRs AI driven?

Yes we are using AI to do scans for potential security issues. I anticipate there will be communication on that once we've patched any issues.

And in light of that, the scans will flag potential issues but it doesn't know all the true use cases, so if there are legitimate cross container use cases, we need to make sure we're not blocking those but marking them in the code. I am not as familiar with this code so please let us know if there are any true needs for cross container functionality.

@bbimber

bbimber commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

OK. The two things that come to mind are the shared container and scenarios involving workbooks/parent. I am pretty sure the experiment service deals with these, but I'm not in front of my computer and haven't thought about this in a while.

If you can wait a day I'll look at this tomorrow.

@labkey-martyp

Copy link
Copy Markdown
Author

OK. The two things that come to mind are the shared container and scenarios involving workbooks/parent. I am pretty sure the experiment service deals with these, but I'm not in front of my computer and haven't thought about this in a while.

If you can wait a day I'll look at this tomorrow.

No rush.

The assay containers that would be in scope and would remain unaffected by these changes as far as I can tell are the 1. the request container, 2. the project root of the request container, 3. the Shared container.

@bbimber bbimber left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AI is technically right here, though the risk is probably not huge. This is a worthwhile change. I cannot think of any cross-container cases that would break from this. AssayService.getAssayProtocols() should handle resolving /Shared and workbook/parent situations.

My only question is around the comments. In general, LK's codebase isnt that verbose with inline comments. This is adding a bunch of redundant explanation. That explanation doesnt really hurt anything. Does LK plan to default to including a lot more comments from these sort of AI PRs?

Also, the AI's 'existence oracle' comment is interesting. There are probably many examples in EHR and related modules that differentiate 'not found' and 'wrong container' in the error messages. It'd be interesting if it finds things like this.

@labkey-martyp

Copy link
Copy Markdown
Author

Yes, point taken on the comments. Usually AI will try to match the coding style of the project, but comments seem to be the exception. Claude in particular can be very verbose with comments. I shortened these.

Yeah we can definitely add the existence Oracle to the list of items to scan across the whole LK database.

There will be more checks to come. I'll probably have another PR or two in this area.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants