Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fbc4be8
Add an XSS example that uses `sap/ui/core/EventBus`
jeongsoolee09 Nov 19, 2025
d7a8b30
Add the first draft of working query
jeongsoolee09 Nov 24, 2025
77c96b1
Update expected results for both jobs
jeongsoolee09 Nov 24, 2025
969c218
Regress to previous expected file to unblock check
jeongsoolee09 Nov 24, 2025
3e5255a
Expected file from Action summary
mbaluda Nov 25, 2025
9331ad5
Merge branch 'main' into jeongsoolee09/add-eventbus-example
jeongsoolee09 Dec 4, 2025
7a020d2
Ensure that the channel name and the message types are matched
jeongsoolee09 Dec 11, 2025
4e32adc
Merge branch 'jeongsoolee09/add-eventbus-example' of github.com:advan…
jeongsoolee09 Dec 11, 2025
3fde2af
Add hierarchy of EventBus classes
jeongsoolee09 Dec 11, 2025
28b78dc
Renaming of abstract predicate
jeongsoolee09 Dec 11, 2025
94b0b8a
Add examples of sap.ui.getCore() and this.getOwnerComponent()
jeongsoolee09 Dec 12, 2025
29e0862
Fix minor bug in the regex
jeongsoolee09 Dec 12, 2025
e3ff3c0
Checkpoint
jeongsoolee09 Dec 12, 2025
4779663
Checkpoint
jeongsoolee09 Dec 12, 2025
b05963e
Final draft
jeongsoolee09 Dec 12, 2025
44dc40e
Update expected file of code scanning
jeongsoolee09 Dec 12, 2025
15ff2eb
Remove test predicates
jeongsoolee09 Dec 15, 2025
fcf43dc
Port ControlTypeInHandlerModel to QL
jeongsoolee09 Dec 15, 2025
904b1fe
Fix bug in UI5ControlHandlerParameter
jeongsoolee09 Dec 15, 2025
6876bcb
Add UI5HTMLControlReferenceContentAPI
jeongsoolee09 Dec 15, 2025
d665b93
Introduce hierarchy on control-related API calls
jeongsoolee09 Dec 15, 2025
f75f848
Remove ControlTypeInHandlerModel and minor formatting
jeongsoolee09 Dec 15, 2025
af948b0
Merge branch 'main' into jeongsoolee09/add-eventbus-example
jeongsoolee09 Dec 15, 2025
dd9277e
Revert hack in `ControlReference`
jeongsoolee09 Dec 15, 2025
66a4ddc
Update expected results of Code Scanning
jeongsoolee09 Dec 15, 2025
a82f5ad
Add `subscribeOnce` as recognized subscription API
jeongsoolee09 Dec 15, 2025
51d9cce
Add documentation comments on branches
jeongsoolee09 Dec 15, 2025
8a8fff2
Remove commented-out test predicate
jeongsoolee09 Dec 15, 2025
98a596f
Add goodies
jeongsoolee09 Dec 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/javascript.sarif.expected

Large diffs are not rendered by default.

32 changes: 31 additions & 1 deletion javascript/frameworks/ui5/ext/ui5.model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ extensions:
pack: codeql/javascript-all
extensible: "typeModel"
data:
- ["SapUICoreInstance", "global", "Member[sap].Member[ui].Member[getCore].ReturnValue"]
- ["Control", "Control", "Instance"]
- ["Control", "sap/ui/core/Control", ""]
- ["Control", "global", "Member[sap].Member[ui].Member[core].Member[Control]"]
- ["Controller", "Controller", "Instance"]
- ["Controller", "sap/ui/core/mvc/Controller", ""]
- ["Component", "sap/ui/core/mvc/Component", ""]
- ["Component", "sap/ui/core/UIComponent", ""]
- ["Renderer", "Control", "Member[extend].Argument[1].Member[renderer]"]
- ["Renderer", "sap/ui/core/RenderManager", "Member[extend].Argument[1].Member[renderer]"]
- ["Renderer", "sap/ui/core/Renderer", "Member[extend].Argument[1]"]
- ["Renderer", "sap/ui/core/Renderer", "Member[extend].Argument[1]"] # ?
- ["RenderManager", "RenderManager", "Instance"]
- ["RenderManager", "sap/ui/core/RenderManager", ""]
- ["RenderManager", "Renderer", "Parameter[0]"]
Expand Down Expand Up @@ -71,6 +76,31 @@ extensions:
- ["UI5ClientStorage", "global", "Member[jQuery].Member[sap].Member[storage]"]
- ["UI5ClientStorage", "sap/ui/core/util/File", ""]
- ["UI5ClientStorage", "global", "Member[sap].Member[ui].Member[core].Member[util].Member[File]"]
# Publishing and Subscribing to Events
- ["UI5EventBusInstance", "sap/ui/core/EventBus", "Member[getInstance].ReturnValue"]
- ["UI5EventBusPublish", "UI5EventBusInstance", "Member[publish]"]
- ["UI5EventBusPublishedEventData", "UI5EventBusPublish", "Argument[2]"]
- ["UI5EventBusSubscribe", "UI5EventBusInstance", "Member[subscribe,subscribeOnce]"]
- ["UI5EventSubscriptionHandlerDataParameter", "UI5EventBusSubscribe", "Argument[2].Parameter[2]"]
- ["SapUICoreEventBusInstance", "SapUICoreInstance", "Member[getEventBus].ReturnValue"]
- ["SapUICoreEventBusPublish", "SapUICoreEventBusInstance", "Member[publish]"]
- ["SapUICoreEventBusPublishedEventData", "SapUICoreEventBusPublish", "Argument[2]"]
- ["SapUICoreEventBusSubscribe", "SapUICoreEventBusInstance", "Member[subscribe,subscribeOnce]"]
- ["SapUICoreEventSubscriptionHandlerDataParameter", "SapUICoreEventBusSubscribe", "Argument[2].Parameter[2]"]
# Extend Calls
- ["CustomControl", "Control", "Member[extend]"]
- ["CustomController", "Controller", "Member[extend]"]
- ["CustomControllerContent", "Controller", "Member[extend].Argument[1]"]
- ["CustomControllerGetOwnerComponent", "CustomControllerContent", "Fuzzy.Member[getOwnerComponent].ReturnValue"]
- ["CustomControllerGetOwnerComponentEventBus", "CustomControllerGetOwnerComponent", "Member[getEventBus].ReturnValue"]
- ["CustomControllerGetOwnerComponentEventBusPublish", "CustomControllerGetOwnerComponentEventBus", "Member[publish]"]
- ["CustomControllerGetOwnerComponentEventBusPublishedData", "CustomControllerGetOwnerComponentEventBusPublish", "Argument[2]"]
- ["CustomControllerGetOwnerComponentEventBusSubscribe", "CustomControllerGetOwnerComponentEventBus", "Member[subscribe,subscribeOnce]"]
- ["CustomControllerGetOwnerComponentEventBusSubscriptionHandlerDataParameter", "CustomControllerGetOwnerComponentEventBusSubscribe", "Argument[2].Parameter[2]"]
- ["CustomComponent", "Component", "Member[extend]"]
- ["CustomRenderer", "Renderer", "Member[extend]"]
- ["ViewReference", "CustomController", "Member[getView].ReturnValue"]
- ["ControlReference", "ViewReference", "Member[byId].ReturnValue"]

- addsTo:
pack: codeql/javascript-all
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,47 @@ import advanced_security.javascript.frameworks.ui5.UI5View
import semmle.javascript.security.dataflow.XssThroughDomCustomizations
private import semmle.javascript.frameworks.data.internal.ApiGraphModelsExtensions

private class DataFromRemoteControlReference extends RemoteFlowSource {
DataFromRemoteControlReference() {
exists(UI5Control sourceControl, string typeAlias, ControlReference controlReference |
abstract private class RemoteControlAPISource extends SourceNode { }

private class RemoteControlReference extends RemoteControlAPISource, ControlReference {
RemoteControlReference() {
exists(UI5Control sourceControl, string typeAlias |
typeModel(typeAlias, sourceControl.getImportPath(), _) and
sourceModel(typeAlias, _, "remote", _) and
sourceControl.getAReference() = controlReference and
(
this = controlReference.getAMemberCall("getValue") or
this = controlReference.getAPropertyRead("value")
)
sourceControl.getAReference() = this
)
}
}

override string getSourceType() { result = "Data from a remote control" }
private class RemoteControlHandlerParameter extends RemoteControlAPISource, CallNode {
RemoteControlHandlerParameter() {
exists(UI5Control sourceControl, string typeAlias, UI5Handler handler |
typeModel(typeAlias, sourceControl.getImportPath(), _) and
sourceModel(typeAlias, _, "remote", _) and
handler.getControl() = sourceControl and
this = handler.getParameter(0).getAMemberCall("getSource")
)
}
}

private class UserDataFromRemoteControlAPISource extends RemoteFlowSource {
UserDataFromRemoteControlAPISource() {
exists(RemoteControlAPISource remoteControlAPISource |
/*
* 1. The `value` or its getter of `HTML` control reference, `CodeEditor` control reference,
* or handler parameters.
*/

this = remoteControlAPISource.getAPropertyRead("value") or
this = remoteControlAPISource.getAMemberCall("getValue") or
/* 2. The `getCurrentValue` method call on `CodeEditor` control reference. */
this = remoteControlAPISource.getAMemberCall("getCurrentValue")
)
}

override string getSourceType() {
result = "User-provided data fetched from an input control via JavaScript API"
}
}

private class InputControlInstantiation extends ElementInstantiation {
Expand Down Expand Up @@ -90,42 +117,23 @@ class ODataServiceModel extends UI5ExternalModel {
override string getSourceType() { result = "ODataServiceModel" }

ODataServiceModel() {
exists(MethodCallNode setModelCall, CustomController controller |
/*
* 1. This flows from a DF node corresponding to the parent component's model
* to the `this.setModel` call. e.g.
*
* `this.getOwnerComponent().getModel("someModelName")` as in
* `this.getView().setModel(this.getOwnerComponent().getModel("someModelName"))`.
*/

modelName = this.getArgument(0).getALocalSource().asExpr().(StringLiteral).getValue() and
exists(CustomController controller |
this.getCalleeName() = "getModel" and
controller.getOwnerComponentRef().flowsTo(this.(MethodCallNode).getReceiver()) and
this.flowsTo(setModelCall.getArgument(0)) and
setModelCall = controller.getAViewReference().getAMemberCall("setModel") and
/*
* 2. The component's `manifest.json` declares the DataSource as being of OData type.
*/

modelName = this.getArgument(0).getALocalSource().getStringValue() and
controller.getOwnerComponent().getExternalModelDef(modelName).getDataSource() instanceof
ODataDataSourceManifest
ODataDataSourceManifest // A component's `manifest.json` declares the data source as being of OData type.
)
or
/*
* A constructor call to sap.ui.model.odata.v2.ODataModel or sap.ui.model.odata.v4.ODataModel.
* A constructor call to `sap.ui.model.odata.v2.ODataModel` or `sap.ui.model.odata.v4.ODataModel`.
*/

this instanceof NewNode and
(
exists(RequiredObject oDataModel |
oDataModel.asSourceNode().flowsTo(this.getCalleeNode()) and
oDataModel.getDependency() in [
"sap/ui/model/odata/v2/ODataModel", "sap/ui/model/odata/v4/ODataModel"
]
)
or
this.getCalleeName() = "ODataModel"
exists(RequiredObject oDataModel |
oDataModel.asSourceNode().flowsTo(this.getCalleeNode()) and
oDataModel.getDependency() in [
"sap/ui/model/odata/v2/ODataModel", "sap/ui/model/odata/v4/ODataModel"
]
) and
modelName = "<no name>"
}
Expand Down
Loading