-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
JS: support hana
db client
#19118
JS: support hana
db client
#19118
Conversation
…t from `hdbext`.
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 adds support for the SAP HANA database client by modeling SQL injection sinks for the @sap/hana-client, @sap/hdbext, and hdb packages.
- Added new test cases in the hana.js file to simulate SQL injection scenarios.
- Introduced a YAML extension model file to map SQL injection sinks for the supported packages.
- Updated the change notes to reflect the new enhancements.
Reviewed Changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.
File | Description |
---|---|
javascript/ql/test/query-tests/Security/CWE-089/untyped/hana.js | New test cases demonstrating various SQL injection sink flows. |
javascript/ql/lib/ext/hana-db-client.model.yml | YAML file mapping methods to SQL injection sinks for the packages. |
javascript/ql/lib/change-notes/2025-03-26-hana-db-client.md | Added change notes documenting the support for the new clients. |
Files not reviewed (1)
- javascript/ql/test/query-tests/Security/CWE-089/untyped/SqlInjection.expected: Language not supported
Comments suppressed due to low confidence (1)
javascript/ql/test/query-tests/Security/CWE-089/untyped/hana.js:38
- [nitpick] The 'express' module is imported twice with different variable declarations; consider using 'const' consistently for clarity and maintainability.
var express = require('express');
Tip: If you use Visual Studio Code, you can request a review from Copilot before you push from the "Source Control" tab. Learn more
let maliciousInput = req.body.data; // $ MISSING: Source | ||
client.exec('SELECT * FROM DUMMY' + maliciousInput, function (err, rs) {}); // $ MISSING: Alert | ||
|
||
dbStream.createProcStatement(client, 'CALL PROC_DUMMY (?, ?, ?, ?, ?)' + maliciousInput, function (err, stmt) { // $ MISSING: Alert |
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'm not sure this is technically SQL injection. It's loading a stored procedure, and calling that with some arguments.
An attacker can definitely not do the usual SQL-injection attacks (e.g. inserting " OR 1=1 "
).
But it still seems wrong to allow a user to control that string, so I suppose it's fine.
Did you have any thoughts on this kind of sink?
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.
The concern I had was that, while typical SQL injection might not be possible, there's still a risk that users could invoke procedures they shouldn’t have access to or perform other unauthorized actions. 🤔
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 it's fine to err on the side of generating more alerts rather than fewer alerts for this case.
var client = req.db; | ||
let maliciousInput = req.body.data; // $ Source | ||
client.exec('SELECT * FROM DUMMY' + maliciousInput, function (err, rs) {}); // $ MISSING: Alert | ||
client.exec('SELECT * FROM DUMMY' + maliciousInput, function (err, rs) {}); // $ Alert |
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.
It would have been nice to restrict this sink to only the cases where we've detected the app1.use(hdbext.middleware(hanaConfig));
call.
But we can't express that with MaD.
So this will support all databases that attach themselves to the req.db
property (and have an exec(..)
method).
I think that's fine, but I would like a second opinion @asgerf.
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, I'm definitely not proud of the way I wrote this SQL
sink, but I couldn't think of a way to express that in Model as Data. 🙈 The odds seem to be very low that there would exist path like this unrelated to hdbext.middleware(hanaConfig)
.
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'd like to go the extra mile here in order to make this work properly, because it's quite common to extend request/response objects from middlewares.
I'll aim to put up a PR that adds support for a new access path component called GuardedRouteHandler
which should do what we need here. The idea is that it goes from the middleware object to all the route handlers guarded by it.
We should then be able to write the model like this:

I have a working proof of concept locally just need to polish it up a bit.
You can either
- leave this PR open and wait for
GuardedRouteHandler
support, or - remove the
express
line from the model and mark the alerts asMISSING
and merge as it is. I'll add it back when addingGuardedRouteHandler
support.
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.
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'll leave this PR open and wait for GuardedRouteHandler support.
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.
Fixed f3af23e
Co-authored-by: Erik Krogh Kristensen <[email protected]>
b79d906
to
f887c4c
Compare
f887c4c
to
45c8ec9
Compare
extensible: typeModel | ||
data: | ||
- ["hdb.Client", "hdb", "Member[createClient].ReturnValue"] | ||
- ["hdb.Client", "@sap/hdbext", "Member[middleware].ReturnValue.GuardedRouteHandler.Parameter[0].Member[db]"] |
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.
Could you also add a test that reg.db.exec(..)
isn't a sink when there is no call to hdb.createClient()
.
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 32d6ac8
…o `Express` are not flagged.
01ff06e
to
32d6ac8
Compare
Modeled
@sap/hana-client
,@sap/hdbext
andhdb
packages sql-injection sinks.