-
Notifications
You must be signed in to change notification settings - Fork 2
Restrict RemoteFlowSource
of CAP to only some properties and method calls on it
#208
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
base: main
Are you sure you want to change the base?
Restrict RemoteFlowSource
of CAP to only some properties and method calls on it
#208
Conversation
- `service3nocds.js` had a service that was named differently. Clarified the gist of the file using tags. - `service4.js` was identical to `service3nocds.js`, except for the `cds.serve` call. This is better suited for `server.js`. - Since `HandlerParameterOfExposedService` is no longer a `RemoteFlowSource`, we place another query for testing it only. - The case categorization is as follows: - `service1`: Exposed service with reads from properties and method calls, some of which are tainted and not tainted. - `service2`: Service that both receives data from service1 and service4 but does not propagate it further. - `service3`: Service without a CDS declaration, simulating extraction failure. Should be recognized as exposed, from overapproximation. Consists of identical property reads / method calls as those of `service1`. - `service4`: Service that is explicitly declared as internal only. Consists of identical property reads / method calls as those of `service1`, but is not a taint source from being unexposed.
The locations changed a little from altering the definition of `RemoteFlowSource` to the property reads of the parameter, not the parameter itself.
- `server.js` had a reference to a service that doesn't exist. Made it point to Service1 instead. - Create expected results of `ExposedServices`, a complementary test to `RemoteFlowSource`.
The results from query predicates changed a little from altering the definition of `RemoteFlowSource` to the property reads of the parameter, not the parameter itself.
@@ -0,0 +1,45 @@ | |||
const cds = require("@sap/cds"); | |||
|
|||
module.exports = class Service5 extends cds.ApplicationService { |
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.
hm I am seeing something I dont quite understand
this testcase fails for me locally, these req locations show up ,
I think its bc this is named service 5 even tho its 4 and 4 is not exposed,
so for a not defined service yes we assume its exposed. ie this should just be service 4, its a typo?
but then why doesnt the CI of the unit tests see that fail?
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.
Ah, good catch, that's a typo. I should have let you know about how to properly run the tests, sorry! I'll put it in the PR body.
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.
Added as a section titled Running the test locally
.
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.
One minor question about an expected result.
| srv/service1.js:7:19:7:35 | { messageToPass } | srv/service1.js:7:21:7:33 | messageToPass | | ||
| srv/service1.js:7:19:7:46 | messageToPass | srv/service1.js:9:38:9:50 | messageToPass | | ||
| srv/service1.js:7:21:7:33 | messageToPass | srv/service1.js:7:19:7:46 | messageToPass | | ||
| srv/service1.js:7:39:7:41 | req | srv/service1.js:7:39:7:46 | req.data | | ||
| srv/service1.js:7:39:7:46 | req.data | srv/service1.js:7:19:7:35 | { messageToPass } | |
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.
New duplicate result?
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, that's expected. In fact, I've noticed this kind of duplicate results even before the changes. These show up when:
N1
-->N3
, andN2
-->N3
, butN1
!=N2
, withN1
's location ==N2
's location.
Here, N1
is an internal node (that has both parent(s) and child(ren)) req.data
whose predecessor is req, and N2 is req.data
is a root node without a predecesor, because it is a RemoteFlowSource
.
} | ||
module.exports = TestService | ||
|
||
cds.serve('./test-service').with((srv) => { |
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.
these had been a bit of an equivalence class test to show that even when the service is not defined (in cds) and there are the non typical registrations out of the init function it is still valid
for example
https://github.com/mpilo-integrove/sap-btp/blob/main/projects/it-inventory/srv/inventory-service.js#L4
but also, that is likely rarer, so if not having even one case of that in a file with a more uniform naming makes sense, then that is fair too!
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.
Good point. But I see in the example that the inventory-service
is an existing service declared in inventory-service.cds
, and inventory-service.js
is implementing it in an unconventional way (I guess the encouraged way is through cds.ApplicationService
).
But I guess having a case of cds.serve(...).with(...)
for a service lacking a CDS declaration will be valuable, as it is another example of service we consider exposed. Service3
is one such example so I'll add a cds.serve("Service3").with((req) => { ... })
.
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.
Added in commit 3a328ad.
Add a `cds.serve(...).with(...)` that expands the functionality of Service3 which lacks a CDS declaration. Since Service3 is missing a CDS declaration, all of the handlers registrated in the `.with` method call should be considered as exposed.
What This PR Contributes
Refine the definition of the remote flow source of CAP
This PR refines the remote flow source of CAP by restricting the definition to reads of property on the program elements previously detected as remote flow sources, namely, parameters of handlers belonging to a service that is exposed to a web protocol. This PR achieves it through the following changes:
HandlerParameterOfExposedService
extendRemoteFlowSource
, andUserProvidedPropertyReadOfHandlerParameterOfExposedService
and make it extend that instead.Enhance unit tests in
remoteflowsources
Tidy up the test project
The test project had several rooms of improvement:
cds.serve(...).with(...)
calls are typically stored in a main entrypoint, so move it there (even if it's technically allowed to be place anywhere).Make another model test query
Also, this PR adds another complementary unit test,
ExposedServices
that tests the classHandlerParameterOfExposedService
, now demoted from being a remote flow source. It is still an important class so we would want to still test if it is working properly.Running the test locally
First, compile the
.cds
files by running the scriptextractors/cds/tools/workflow/cds-compilation-for-actions.sh
. Then, runexport LGTM_INDEX_FILTERS=include:**/*.json
to enable JSON extraction for your shell session. You should be prepared to create the database withcodeql database create --language=javascript
.Future Works
requesthandler
, and what it intends to test is already covered in this unit test. So, it can be safely deleted.cds.serve(...)
can also accept a path string relative to the entrypoint of the root of the application, but it is not yet modeled. Modeling it can be a future work.