Sensei Feature Highlight: Library Scope
Manage dependencies flexibly
The Scope functionality of Sensei has always been a favorite of developers. With the ability to expand or limit the scope of a recipe’s application, development teams have been able to customize its usage to individual projects and verticals within their organizations - empowering developers to personalize their experience.
And understandably, it is at the center of Sensei’s continuous innovation processes. During an innovation brainstorming session on expanding the scope of “scope” (yes, pun intended), a question came up:
"I was trying to create a recipe for ... but since version x, the framework has deprecated the feature. I am not sure whether it will be useful to create a recipe anymore. What do you think?"
Of course, this is not the first time we have hesitated to create a recipe. While the recipe might be seen as providing redundant information, we believe it is valuable to create something that is applicable to a limited number of versions of the involved dependency. And therefore, we created the Library scope.
Library scope enables us to check whether a dependency is present in the project and conditionally apply Sensei recipes. This gives great flexibility as teams navigate through legacy code and dependencies.
Many of you might know of the Library scope that is already available under General Settings. So what is this you ask? We have enabled Library Scope to be present in YAML, just like the search. This creates a better user experience and does not break your flow as you create the recipe, which otherwise would have you navigate to General Settings and back to update metadata. More of these scopes will come into YAML but we have started with the Library Scope.
So let us dive a little further into how it works with an example.
Library scope applied to hibernate-jpamodelgen
Imagine the following case:
We want to create a Spring Web REST API that allows us to query some data. According to the best practices, we create a model for the entity we want to query. Next, we add a dependency to Hibernate ORM, so that we do not need to fiddle with the database structure. The ORM takes care of that for us. We also need to create a service that provides the data from the data access layer (CRUD repositories and so on) to the controller. Finally, we create the controller class for our API, where we will expose the allowed queries as endpoints.
To prevent having to expose different endpoints for each field that can be queried, we instead opt to use JPA 2 Specifications. To do so, we create a specification in the controller from the request URL. This specification describes what the entities we are looking for should look like. In the `Specification` class itself, we implement the `toPredicate` method to indicate how the specification can be validated.
But we are faced with an issue in the `toPredicate` method. To construct the predicate, we need to know the names of the columns in the database to compare. But because we are using an ORM, we do not have these columns present in a separate model. So, Hibernate's JPA 2 Metamodel Generator() comes to the rescue! This will help generate a metamodel for the entities we requested it to handle. These metamodels allow us to reference the column names as properties instead of hardcoding them.
Creating the Sensei recipe
Now that we have the metamodels generated, we want to put them to good use. Sensei can help anyone who works on the project by reminding them to use the metamodel, making sure that column names are not hardcoded anywhere. So let’s put that into practice.
To start, we take a look at the `toPredicate` method:
This basic predicate will only compare the name of our entity. We can expand on it using `and` clauses, but for the purpose of this recipe, this 'simple' check will do.
For the search component of the recipe, we want to call the method `get()` of the root parameter, so we select the `methodcall` option from the dropdown. Next, we want to limit the search to a methodcall with the name `get` whose signature is declared in the `Path` interface of the `javax.persistence.criteria` package. As the method has been overloaded, we also need to tell the search that our recipe only applies to the variant that takes a single string as an argument. To fix the issue of having the column names in the code we would want to use an argument of type `SingularAttribute` instead, the same type provided by the metamodel generator.
The recipe that we have created so far will trigger on any codebase that uses the JPA 2 `Path` interface, regardless of whether the codebase is set up to use the Hibernate Model Generator. If this library is present in the project, we want to indicate to the user that it should be used, so we add a library scope to the recipe.
And finally, our recipe is now ready.
With this recipe, any occurrence of `Path#get` that uses a string value as an argument will be flagged. As you can tell from the highlighted example code in the above screenshot, this recipe still works when the literal name of the column name is stored in an intermediate variable.
Note - We can also invert the library scope to handle the case where the library is not available, by prepending a `not` clause to the scope.
Conclusion
As we have seen in the example above, this new feature enables us to create more useful recipes by applying them based on the presence of dependencies in the project. To enhance its power even further, we included more options than were shown in the example, such as not only checking whether the dependency is present, but also applying conditions to the specific version of the dependency.
The main use cases we see for this feature are preventing recipes from providing duplicate information, detecting issues related to specific versions of dependencies, but also performing migrations from one dependency version to the next. We're looking forward to hearing from you about what uses you see for this feature.
As for all Sensei features, more information on the library scope is available in the reference documentation.
Nick is a dedicated security researcher at Secure Code Warrior, with experience in both software engineering and security. Next to a passion for security, he holds an Msc. Ir. in computer sciences from Ghent University. He’s on a mission to make software safer for all of us.
Secure Code Warrior is here for your organization to help you secure code across the entire software development lifecycle and create a culture in which cybersecurity is top of mind. Whether you’re an AppSec Manager, Developer, CISO, or anyone involved in security, we can help your organization reduce risks associated with insecure code.
Book a demoNick is a dedicated security researcher at Secure Code Warrior, with experience in both software engineering and security. Next to a passion for security, he holds an Msc. Ir. in computer sciences from Ghent University. He’s on a mission to make software safer for all of us.
Manage dependencies flexibly
The Scope functionality of Sensei has always been a favorite of developers. With the ability to expand or limit the scope of a recipe’s application, development teams have been able to customize its usage to individual projects and verticals within their organizations - empowering developers to personalize their experience.
And understandably, it is at the center of Sensei’s continuous innovation processes. During an innovation brainstorming session on expanding the scope of “scope” (yes, pun intended), a question came up:
"I was trying to create a recipe for ... but since version x, the framework has deprecated the feature. I am not sure whether it will be useful to create a recipe anymore. What do you think?"
Of course, this is not the first time we have hesitated to create a recipe. While the recipe might be seen as providing redundant information, we believe it is valuable to create something that is applicable to a limited number of versions of the involved dependency. And therefore, we created the Library scope.
Library scope enables us to check whether a dependency is present in the project and conditionally apply Sensei recipes. This gives great flexibility as teams navigate through legacy code and dependencies.
Many of you might know of the Library scope that is already available under General Settings. So what is this you ask? We have enabled Library Scope to be present in YAML, just like the search. This creates a better user experience and does not break your flow as you create the recipe, which otherwise would have you navigate to General Settings and back to update metadata. More of these scopes will come into YAML but we have started with the Library Scope.
So let us dive a little further into how it works with an example.
Library scope applied to hibernate-jpamodelgen
Imagine the following case:
We want to create a Spring Web REST API that allows us to query some data. According to the best practices, we create a model for the entity we want to query. Next, we add a dependency to Hibernate ORM, so that we do not need to fiddle with the database structure. The ORM takes care of that for us. We also need to create a service that provides the data from the data access layer (CRUD repositories and so on) to the controller. Finally, we create the controller class for our API, where we will expose the allowed queries as endpoints.
To prevent having to expose different endpoints for each field that can be queried, we instead opt to use JPA 2 Specifications. To do so, we create a specification in the controller from the request URL. This specification describes what the entities we are looking for should look like. In the `Specification` class itself, we implement the `toPredicate` method to indicate how the specification can be validated.
But we are faced with an issue in the `toPredicate` method. To construct the predicate, we need to know the names of the columns in the database to compare. But because we are using an ORM, we do not have these columns present in a separate model. So, Hibernate's JPA 2 Metamodel Generator() comes to the rescue! This will help generate a metamodel for the entities we requested it to handle. These metamodels allow us to reference the column names as properties instead of hardcoding them.
Creating the Sensei recipe
Now that we have the metamodels generated, we want to put them to good use. Sensei can help anyone who works on the project by reminding them to use the metamodel, making sure that column names are not hardcoded anywhere. So let’s put that into practice.
To start, we take a look at the `toPredicate` method:
This basic predicate will only compare the name of our entity. We can expand on it using `and` clauses, but for the purpose of this recipe, this 'simple' check will do.
For the search component of the recipe, we want to call the method `get()` of the root parameter, so we select the `methodcall` option from the dropdown. Next, we want to limit the search to a methodcall with the name `get` whose signature is declared in the `Path` interface of the `javax.persistence.criteria` package. As the method has been overloaded, we also need to tell the search that our recipe only applies to the variant that takes a single string as an argument. To fix the issue of having the column names in the code we would want to use an argument of type `SingularAttribute` instead, the same type provided by the metamodel generator.
The recipe that we have created so far will trigger on any codebase that uses the JPA 2 `Path` interface, regardless of whether the codebase is set up to use the Hibernate Model Generator. If this library is present in the project, we want to indicate to the user that it should be used, so we add a library scope to the recipe.
And finally, our recipe is now ready.
With this recipe, any occurrence of `Path#get` that uses a string value as an argument will be flagged. As you can tell from the highlighted example code in the above screenshot, this recipe still works when the literal name of the column name is stored in an intermediate variable.
Note - We can also invert the library scope to handle the case where the library is not available, by prepending a `not` clause to the scope.
Conclusion
As we have seen in the example above, this new feature enables us to create more useful recipes by applying them based on the presence of dependencies in the project. To enhance its power even further, we included more options than were shown in the example, such as not only checking whether the dependency is present, but also applying conditions to the specific version of the dependency.
The main use cases we see for this feature are preventing recipes from providing duplicate information, detecting issues related to specific versions of dependencies, but also performing migrations from one dependency version to the next. We're looking forward to hearing from you about what uses you see for this feature.
As for all Sensei features, more information on the library scope is available in the reference documentation.
Manage dependencies flexibly
The Scope functionality of Sensei has always been a favorite of developers. With the ability to expand or limit the scope of a recipe’s application, development teams have been able to customize its usage to individual projects and verticals within their organizations - empowering developers to personalize their experience.
And understandably, it is at the center of Sensei’s continuous innovation processes. During an innovation brainstorming session on expanding the scope of “scope” (yes, pun intended), a question came up:
"I was trying to create a recipe for ... but since version x, the framework has deprecated the feature. I am not sure whether it will be useful to create a recipe anymore. What do you think?"
Of course, this is not the first time we have hesitated to create a recipe. While the recipe might be seen as providing redundant information, we believe it is valuable to create something that is applicable to a limited number of versions of the involved dependency. And therefore, we created the Library scope.
Library scope enables us to check whether a dependency is present in the project and conditionally apply Sensei recipes. This gives great flexibility as teams navigate through legacy code and dependencies.
Many of you might know of the Library scope that is already available under General Settings. So what is this you ask? We have enabled Library Scope to be present in YAML, just like the search. This creates a better user experience and does not break your flow as you create the recipe, which otherwise would have you navigate to General Settings and back to update metadata. More of these scopes will come into YAML but we have started with the Library Scope.
So let us dive a little further into how it works with an example.
Library scope applied to hibernate-jpamodelgen
Imagine the following case:
We want to create a Spring Web REST API that allows us to query some data. According to the best practices, we create a model for the entity we want to query. Next, we add a dependency to Hibernate ORM, so that we do not need to fiddle with the database structure. The ORM takes care of that for us. We also need to create a service that provides the data from the data access layer (CRUD repositories and so on) to the controller. Finally, we create the controller class for our API, where we will expose the allowed queries as endpoints.
To prevent having to expose different endpoints for each field that can be queried, we instead opt to use JPA 2 Specifications. To do so, we create a specification in the controller from the request URL. This specification describes what the entities we are looking for should look like. In the `Specification` class itself, we implement the `toPredicate` method to indicate how the specification can be validated.
But we are faced with an issue in the `toPredicate` method. To construct the predicate, we need to know the names of the columns in the database to compare. But because we are using an ORM, we do not have these columns present in a separate model. So, Hibernate's JPA 2 Metamodel Generator() comes to the rescue! This will help generate a metamodel for the entities we requested it to handle. These metamodels allow us to reference the column names as properties instead of hardcoding them.
Creating the Sensei recipe
Now that we have the metamodels generated, we want to put them to good use. Sensei can help anyone who works on the project by reminding them to use the metamodel, making sure that column names are not hardcoded anywhere. So let’s put that into practice.
To start, we take a look at the `toPredicate` method:
This basic predicate will only compare the name of our entity. We can expand on it using `and` clauses, but for the purpose of this recipe, this 'simple' check will do.
For the search component of the recipe, we want to call the method `get()` of the root parameter, so we select the `methodcall` option from the dropdown. Next, we want to limit the search to a methodcall with the name `get` whose signature is declared in the `Path` interface of the `javax.persistence.criteria` package. As the method has been overloaded, we also need to tell the search that our recipe only applies to the variant that takes a single string as an argument. To fix the issue of having the column names in the code we would want to use an argument of type `SingularAttribute` instead, the same type provided by the metamodel generator.
The recipe that we have created so far will trigger on any codebase that uses the JPA 2 `Path` interface, regardless of whether the codebase is set up to use the Hibernate Model Generator. If this library is present in the project, we want to indicate to the user that it should be used, so we add a library scope to the recipe.
And finally, our recipe is now ready.
With this recipe, any occurrence of `Path#get` that uses a string value as an argument will be flagged. As you can tell from the highlighted example code in the above screenshot, this recipe still works when the literal name of the column name is stored in an intermediate variable.
Note - We can also invert the library scope to handle the case where the library is not available, by prepending a `not` clause to the scope.
Conclusion
As we have seen in the example above, this new feature enables us to create more useful recipes by applying them based on the presence of dependencies in the project. To enhance its power even further, we included more options than were shown in the example, such as not only checking whether the dependency is present, but also applying conditions to the specific version of the dependency.
The main use cases we see for this feature are preventing recipes from providing duplicate information, detecting issues related to specific versions of dependencies, but also performing migrations from one dependency version to the next. We're looking forward to hearing from you about what uses you see for this feature.
As for all Sensei features, more information on the library scope is available in the reference documentation.
Click on the link below and download the PDF of this resource.
Secure Code Warrior is here for your organization to help you secure code across the entire software development lifecycle and create a culture in which cybersecurity is top of mind. Whether you’re an AppSec Manager, Developer, CISO, or anyone involved in security, we can help your organization reduce risks associated with insecure code.
View reportBook a demoNick is a dedicated security researcher at Secure Code Warrior, with experience in both software engineering and security. Next to a passion for security, he holds an Msc. Ir. in computer sciences from Ghent University. He’s on a mission to make software safer for all of us.
Manage dependencies flexibly
The Scope functionality of Sensei has always been a favorite of developers. With the ability to expand or limit the scope of a recipe’s application, development teams have been able to customize its usage to individual projects and verticals within their organizations - empowering developers to personalize their experience.
And understandably, it is at the center of Sensei’s continuous innovation processes. During an innovation brainstorming session on expanding the scope of “scope” (yes, pun intended), a question came up:
"I was trying to create a recipe for ... but since version x, the framework has deprecated the feature. I am not sure whether it will be useful to create a recipe anymore. What do you think?"
Of course, this is not the first time we have hesitated to create a recipe. While the recipe might be seen as providing redundant information, we believe it is valuable to create something that is applicable to a limited number of versions of the involved dependency. And therefore, we created the Library scope.
Library scope enables us to check whether a dependency is present in the project and conditionally apply Sensei recipes. This gives great flexibility as teams navigate through legacy code and dependencies.
Many of you might know of the Library scope that is already available under General Settings. So what is this you ask? We have enabled Library Scope to be present in YAML, just like the search. This creates a better user experience and does not break your flow as you create the recipe, which otherwise would have you navigate to General Settings and back to update metadata. More of these scopes will come into YAML but we have started with the Library Scope.
So let us dive a little further into how it works with an example.
Library scope applied to hibernate-jpamodelgen
Imagine the following case:
We want to create a Spring Web REST API that allows us to query some data. According to the best practices, we create a model for the entity we want to query. Next, we add a dependency to Hibernate ORM, so that we do not need to fiddle with the database structure. The ORM takes care of that for us. We also need to create a service that provides the data from the data access layer (CRUD repositories and so on) to the controller. Finally, we create the controller class for our API, where we will expose the allowed queries as endpoints.
To prevent having to expose different endpoints for each field that can be queried, we instead opt to use JPA 2 Specifications. To do so, we create a specification in the controller from the request URL. This specification describes what the entities we are looking for should look like. In the `Specification` class itself, we implement the `toPredicate` method to indicate how the specification can be validated.
But we are faced with an issue in the `toPredicate` method. To construct the predicate, we need to know the names of the columns in the database to compare. But because we are using an ORM, we do not have these columns present in a separate model. So, Hibernate's JPA 2 Metamodel Generator() comes to the rescue! This will help generate a metamodel for the entities we requested it to handle. These metamodels allow us to reference the column names as properties instead of hardcoding them.
Creating the Sensei recipe
Now that we have the metamodels generated, we want to put them to good use. Sensei can help anyone who works on the project by reminding them to use the metamodel, making sure that column names are not hardcoded anywhere. So let’s put that into practice.
To start, we take a look at the `toPredicate` method:
This basic predicate will only compare the name of our entity. We can expand on it using `and` clauses, but for the purpose of this recipe, this 'simple' check will do.
For the search component of the recipe, we want to call the method `get()` of the root parameter, so we select the `methodcall` option from the dropdown. Next, we want to limit the search to a methodcall with the name `get` whose signature is declared in the `Path` interface of the `javax.persistence.criteria` package. As the method has been overloaded, we also need to tell the search that our recipe only applies to the variant that takes a single string as an argument. To fix the issue of having the column names in the code we would want to use an argument of type `SingularAttribute` instead, the same type provided by the metamodel generator.
The recipe that we have created so far will trigger on any codebase that uses the JPA 2 `Path` interface, regardless of whether the codebase is set up to use the Hibernate Model Generator. If this library is present in the project, we want to indicate to the user that it should be used, so we add a library scope to the recipe.
And finally, our recipe is now ready.
With this recipe, any occurrence of `Path#get` that uses a string value as an argument will be flagged. As you can tell from the highlighted example code in the above screenshot, this recipe still works when the literal name of the column name is stored in an intermediate variable.
Note - We can also invert the library scope to handle the case where the library is not available, by prepending a `not` clause to the scope.
Conclusion
As we have seen in the example above, this new feature enables us to create more useful recipes by applying them based on the presence of dependencies in the project. To enhance its power even further, we included more options than were shown in the example, such as not only checking whether the dependency is present, but also applying conditions to the specific version of the dependency.
The main use cases we see for this feature are preventing recipes from providing duplicate information, detecting issues related to specific versions of dependencies, but also performing migrations from one dependency version to the next. We're looking forward to hearing from you about what uses you see for this feature.
As for all Sensei features, more information on the library scope is available in the reference documentation.
Table of contents
Nick is a dedicated security researcher at Secure Code Warrior, with experience in both software engineering and security. Next to a passion for security, he holds an Msc. Ir. in computer sciences from Ghent University. He’s on a mission to make software safer for all of us.
Secure Code Warrior is here for your organization to help you secure code across the entire software development lifecycle and create a culture in which cybersecurity is top of mind. Whether you’re an AppSec Manager, Developer, CISO, or anyone involved in security, we can help your organization reduce risks associated with insecure code.
Book a demoDownloadResources to get you started
Benchmarking Security Skills: Streamlining Secure-by-Design in the Enterprise
The Secure-by-Design movement is the future of secure software development. Learn about the key elements companies need to keep in mind when they think about a Secure-by-Design initiative.
DigitalOcean Decreases Security Debt with Secure Code Warrior
DigitalOcean's use of Secure Code Warrior training has significantly reduced security debt, allowing teams to focus more on innovation and productivity. The improved security has strengthened their product quality and competitive edge. Looking ahead, the SCW Trust Score will help them further enhance security practices and continue driving innovation.
Resources to get you started
Trust Score Reveals the Value of Secure-by-Design Upskilling Initiatives
Our research has shown that secure code training works. Trust Score, using an algorithm drawing on more than 20 million learning data points from work by more than 250,000 learners at over 600 organizations, reveals its effectiveness in driving down vulnerabilities and how to make the initiative even more effective.
Reactive Versus Preventive Security: Prevention Is a Better Cure
The idea of bringing preventive security to legacy code and systems at the same time as newer applications can seem daunting, but a Secure-by-Design approach, enforced by upskilling developers, can apply security best practices to those systems. It’s the best chance many organizations have of improving their security postures.
The Benefits of Benchmarking Security Skills for Developers
The growing focus on secure code and Secure-by-Design principles requires developers to be trained in cybersecurity from the start of the SDLC, with tools like Secure Code Warrior’s Trust Score helping measure and improve their progress.
Driving Meaningful Success for Enterprise Secure-by-Design Initiatives
Our latest research paper, Benchmarking Security Skills: Streamlining Secure-by-Design in the Enterprise is the result of deep analysis of real Secure-by-Design initiatives at the enterprise level, and deriving best practice approaches based on data-driven findings.