-
Notifications
You must be signed in to change notification settings - Fork 3
Ensure sanitizeContent attribute is respected #257
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?
Conversation
javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-control sanitized/UI5Xss.qlref
Fixed
Show fixed
Hide fixed
...script/frameworks/ui5/test/queries/UI5Xss/xss-html-control-df sanitized-disable/UI5Xss.qlref
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-control-df sanitized/UI5Xss.qlref
Fixed
Show fixed
Hide fixed
...pt/frameworks/ui5/test/queries/UI5Xss/xss-html-control-df sanitized/webapp/view/app.view.xml
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-view sanitized/UI5Xss.qlref
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-js-view sanitized/UI5Xss.qlref
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-json-view sanitized/UI5Xss.qlref
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-view sanitized/webapp/view/app.view.html
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-js-view sanitized/webapp/view/app.view.js
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-json-view sanitized/webapp/view/app.view.json
Fixed
Show fixed
Hide fixed
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5Control.qll
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5Control.qll
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5Control.qll
Fixed
Show fixed
Hide fixed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-control/webapp/view/app.view.xml
Dismissed
Show dismissed
Hide dismissed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-control/webapp/view/app.view.xml
Dismissed
Show dismissed
Hide dismissed
javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-control/webapp/view/app.view.xml
Dismissed
Show dismissed
Hide dismissed
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.
Pull request overview
This PR enhances the CodeQL analysis for UI5 applications by ensuring the sanitizeContent attribute is properly respected when detecting HTML injection vulnerabilities. The changes extract control-related logic into a dedicated module and improve the detection of sanitized vs. unsanitized HTML controls across all view types (XML, JSON, and JavaScript).
Key changes:
- Extracted
UI5ControlandUI5ControlPropertyclasses fromUI5View.qllinto a newUI5Control.qllfile - Introduced
isSanitizedControl()predicate to identify controls with sanitization enabled/disabled both declaratively and programmatically - Updated HTML injection sink detection to exclude sanitized controls from vulnerability reports
- Enhanced test coverage with scenarios for declarative and programmatic sanitization control
- Upgraded CodeQL GitHub Actions from v3 to v4
Reviewed changes
Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5Control.qll | New file containing extracted UI5Control and UI5ControlProperty classes with isSanitizedControl() predicate for sanitization detection |
| javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5View.qll | Removed UI5Control and UI5ControlProperty class definitions (moved to UI5Control.qll) and removed XML-specific sanitization checks |
| javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5.qll | Added import for new UI5Control module |
| javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/dataflow/DataFlow.qll | Added sanitization check to filter sanitized controls from HTML injection sinks |
| javascript/frameworks/ui5/test/models/sink/UI5ViewSinkTest.ql | Updated query to exclude sanitized controls from sink detection |
| javascript/frameworks/ui5/test/models/sink/sink1.xml | Added test case for sanitized HTML control |
| javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-control/webapp/view/app.view.xml | Added comprehensive test cases for declarative and programmatic sanitization scenarios |
| javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-control/webapp/controller/app.controller.js | Added controller logic to test programmatic sanitization control via setProperty() |
| javascript/frameworks/ui5/test/queries/UI5Xss/xss-html-control/UI5Xss.expected | Updated expected results to reflect proper sanitization detection |
| javascript/frameworks/ui5/test/queries/UI5Xss/xss-json-view/webapp/view/app.view.json | Added test case for sanitized HTML control in JSON view |
| javascript/frameworks/ui5/test/queries/UI5Xss/xss-json-view/UI5Xss.expected | Updated expected results for JSON view sanitization |
| javascript/frameworks/ui5/test/queries/UI5Xss/xss-js-view/webapp/view/app.view.js | Added test case for sanitized HTML control in JS view |
| javascript/frameworks/ui5/test/queries/UI5Xss/xss-js-view/UI5Xss.expected | Updated expected results for JS view sanitization |
| javascript/frameworks/ui5/test/README.md | Updated documentation to describe sanitization testing scenarios |
| .github/workflows/code_scanning.yml | Upgraded CodeQL Actions from v3 to v4 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5Control.qll
Outdated
Show resolved
Hide resolved
javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/dataflow/DataFlow.qll
Show resolved
Hide resolved
javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5Control.qll
Outdated
Show resolved
Hide resolved
| //or | ||
| // `sanitizeContent` attribute is set programmatically (not sufficient) | ||
| //result | ||
| // .getAReference() | ||
| // .hasPropertyWrite("sanitizeContent", | ||
| // any(DataFlow::Node n | not n.mayHaveBooleanValue(val.booleanNot()))) |
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 think you should bring this back (possibly refined), as I guess it's to cover cases where the property is directly written to using assignment.
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 created a test for that and the HTML is not sanitized
javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5Control.qll
Outdated
Show resolved
Hide resolved
javascript/frameworks/ui5/lib/advanced_security/javascript/frameworks/ui5/UI5Control.qll
Outdated
Show resolved
Hide resolved
| // enable sanitization programmatically | ||
| this.getView().byId("htmlJsSanitized2").setProperty("sanitizeContent", true); | ||
|
|
||
| // setting the property directly is not sufficient |
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 I ask you what you mean by not sufficient?
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.
Running that example, the XSS still works
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 see, I guess the sap.ui.base.ManagedObject class wraps a plain JS object in a way that disallows direct setting of values using direct assignment.
So, I suggest two things:
- Let's remove this case, and
- Add a case using
setSanitizeContent: It's a special case of generated setters (that we already model for user-defined properties). UI5 automatically generates getters and setters for all properties defined for aManagedObject.
| bindingset[val] | ||
| private UI5Control sanitizeContentSetTo(boolean val) { | ||
| /* 1. `sanitizeContent` attribute is set declaratively. */ | ||
| result.getProperty("sanitizeContent").toString() = val.toString() | ||
| or | ||
| /* 2. `sanitizeContent` attribute is set programmatically using setProperty(). */ | ||
| exists(CallNode node | node = result.getAReference().getAMemberCall("setProperty") | | ||
| node.getArgument(0).getStringValue() = "sanitizeContent" and | ||
| not node.getArgument(1).mayHaveBooleanValue(val.booleanNot()) | ||
| ) | ||
| } |
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.
This can be rewritten to:
| bindingset[val] | |
| private UI5Control sanitizeContentSetTo(boolean val) { | |
| /* 1. `sanitizeContent` attribute is set declaratively. */ | |
| result.getProperty("sanitizeContent").toString() = val.toString() | |
| or | |
| /* 2. `sanitizeContent` attribute is set programmatically using setProperty(). */ | |
| exists(CallNode node | node = result.getAReference().getAMemberCall("setProperty") | | |
| node.getArgument(0).getStringValue() = "sanitizeContent" and | |
| not node.getArgument(1).mayHaveBooleanValue(val.booleanNot()) | |
| ) | |
| } | |
| private predicate sanitizeContentSetToTrue() { | |
| this.getAReference().getAPropertyWrite("sanitizeContent").getRhs().mayHaveBooleanValue(true) | |
| or | |
| exists(CallNode setPropertyCall | | |
| setPropertyCall = this.getAReference().getAMemberCall("setProperty") | |
| | | |
| setPropertyCall.getArgument(0).getStringValue() = "sanitizeContent" and | |
| setPropertyCall.getArgument(1).mayHaveBooleanValue(true) | |
| ) | |
| } |
- Regarding the first disjunct,
DataFlow::PropWriteclass provides a clean way to describe property writes in general. - The second clause of the second disjunct (the
existsclause) contains a double negation. We can straighten it out by negating both. - Since we're describing an instance of this class, we can rewrite it to a result-less predicate and use
thisin place ofresult. This predicate also does not boundthisto a value. - Also, the
sanitizeContentproperty defaults tofalse. So, we're only interested in cases where it's explicitly set totrue. So, we can confine the concern of this predicate to only checking if it's set totrue. This does away with the need forbindingset[val].
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.
Also, taking this into account, we can change the first disjunct:
| bindingset[val] | |
| private UI5Control sanitizeContentSetTo(boolean val) { | |
| /* 1. `sanitizeContent` attribute is set declaratively. */ | |
| result.getProperty("sanitizeContent").toString() = val.toString() | |
| or | |
| /* 2. `sanitizeContent` attribute is set programmatically using setProperty(). */ | |
| exists(CallNode node | node = result.getAReference().getAMemberCall("setProperty") | | |
| node.getArgument(0).getStringValue() = "sanitizeContent" and | |
| not node.getArgument(1).mayHaveBooleanValue(val.booleanNot()) | |
| ) | |
| } | |
| private predicate sanitizeContentSetToTrue() { | |
| this.getAReference().getAMemberCall("setSanitizeContent").getArgument(0).mayHaveBooleanValue(true) | |
| or | |
| exists(CallNode setPropertyCall | | |
| setPropertyCall = this.getAReference().getAMemberCall("setProperty") | |
| | | |
| setPropertyCall.getArgument(0).getStringValue() = "sanitizeContent" and | |
| setPropertyCall.getArgument(1).mayHaveBooleanValue(true) | |
| ) | |
| } |
jeongsoolee09
left a comment
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.
Second round!
Key changes:
UI5 Control and Sanitization Logic
UI5Control.qllfromUI5View.qll. Adds the predicateisSanitizedControlto identify controls where sanitization is enabled or disabled via thesanitizeContentproperty. Works with all kinds of view.UI5 Control and Sanitization Logic
models/sinkxss-html-controlxss-js-viewxss-json-viewREADME)CodeQL Workflow Updates