-
Notifications
You must be signed in to change notification settings - Fork 908
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
Update fileConfigPage.ts #7878
Update fileConfigPage.ts #7878
Conversation
let query = ''; | ||
if (this.databaseDropdown.value !== null) | ||
{ | ||
query = `SELECT name FROM [${this.databaseDropdown.value}].sys.schemas`; |
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 needs to have the ]'s escaped
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.
So what I'm talking about is that you need to escape ]'s in the DB name by doubling them. This is because currently if you try to run that query against a DB that has a ] in its name then you'd end up with a query like this (assuming you have a DB named my]db
)
SELECT name FROM [my]db].sys.schemas
which would break because it would see the ] as the end of the object name and thus have invalid syntax.
So the fix is to do something like this
const query = this.databaseDropdown.value ? 'SELECT name FROM [${this.databaseDropdown.value.replace(/]/g, ']]')}].sys.schemas' : 'SELECT name FROM sys.schemas';
So that you end up with a query like this :
SELECT name FROM [my]]db].sys.schemas
which will then run correctly.
(This also safeguards against the SQL injection issues that were mentioned in the previous PR)
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 am more concerned about spaces in databases names. If they have a bracket in their name I think they have more issues to resolve. I also don't see how SQL injection would play since this is just populating a drop down which is then selected. Unless a user has the ability to adjust the drop down I'm not seeing how they would be able to inject anything.
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.
Bracket-quoting the name is correct, I agree.
But we do require all queries that use values outside of our control to be correctly escaped. And database names fall under that bucket of "out of our control" since a server could have a database with a malicious name (which - while unlikely - is possible).
Unless that is being done correctly we can't take this fix.
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 quite sure how you would escape this, it's not like a quote character. The database names are coming directly from the database connection above which is in control, thus this would also be in control. This isn't a webpage, you can't edit the form and post to your app. Unless I'm missing something here.
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 gave you the code above to escape it (you escape them by replacing every ] with ]]) :
const query = this.databaseDropdown.value ? 'SELECT name FROM [${this.databaseDropdown.value.replace(/]/g, ']]')}].sys.schemas' : 'SELECT name FROM sys.schemas';
Here's a possible situation that we are preventing with this. Some bad actor has somehow gotten access to create DBs on the server but not anything else. They create a DB with this name
master].sys.tables; CREATE LOGIN foo WITH PASSWORD='12345' --
Then another person comes along with more permissions - such as being able to create a login. They open the dialog and your code above will create this query :
SELECT name FROM [master].sys.tables; CREATE LOGIN foo WITH PASSWORD='12345' --].sys.schemas
(Note the rest of the query is commented out because of the --)
This query is ran and now this bad actor has silently caused this other user to create a login on the DB. But you can run any query. This is extremely dangerous and as said - while unlikely to actually happen - is something we can't allow to be a possibility.
@Charles-Gagnon @aspnerd I think the correct solution here is to use
That way you don't have to deal with escaping names. |
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.
We should be using the MetadataProvider
instead of QueryProvider
to list the database names.
@abist - This PR is about fixing the schema dropdown, not the database. And unless I'm missing something the metadata provider doesn't provide a way to query for the schemas so this manual query is necessary until that's added. |
@abist, @Charles-Gagnon is correct, we are looking for schemas not databases for this drop down. The issue at hand is that the drop down populated pulls from master, therefore any selected database you want to import into does not list out the correct or available schemas. I ran into this issue when attempting to import a flat file into our 'Staging' schema, and it was not available on the drop down list. The issue is that if a database name has a space in it, if you don't use brackets it will not return a correct result. I would hope most databases don't have a space, but just in case I've added the brackets. We could remove those, then it would fail on databases with spaces. |
let query = `SELECT name FROM sys.schemas`; | ||
let databaseName = this.databaseDropdown.value.toString().replace(/]/g, ']]'); | ||
|
||
const query = this.databaseDropdown.value ? 'SELECT name FROM [${databaseName}].sys.schemas' : 'SELECT name FROM sys.schemas'; |
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.
You're checking for this.databaseDropdown.value to be truthy here but you've already used it in on line 273 - if it was undefined it would have failed there.
Also I just looked at it myself and the dropdown value is a string | CategoryValue - and specifically in this instance we're populating it with CategoryValue objects. Did you test this yourself? Because I'm surprised it worked with the code you had. Calling toString() on that is just going to return [object Object]
Something like this should work, but you should be testing this yourself too to make sure it works as expected.
const escapedQuotedDb = this.databaseDropdown.value ? `[${(<azdata.CategoryValue>this.databaseDropdown.value).name.replace(/]/g, ']]')}` : '';
const query = `SELECT name FROM ${escapedQuotedDb}.sys.schemas`;
This pull request introduces 1 alert when merging c604abb into 397f6af - view on LGTM.com new alerts:
|
This pull request introduces 1 alert when merging 86493c4 into 03cb056 - view on LGTM.com new alerts:
|
@@ -270,7 +270,8 @@ export class FileConfigPage extends ImportPage { | |||
let connectionUri = await azdata.connection.getUriForConnection(this.model.server.connectionId); | |||
let queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>(this.model.server.providerName, azdata.DataProviderType.QueryProvider); | |||
|
|||
let query = `SELECT name FROM sys.schemas`; | |||
const escapedQuotedDb = this.databaseDropdown.value ? (<azdata.CategoryValue>this.databaseDropdown.value).name.replace(/]/g, ']]') : ''; | |||
const query = 'SELECT name FROM ${escapedQuotedDb}.sys.schemas'; |
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 period should actually also be in the previous part (we don't want to include the period if there isn't a DB name selected)
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.
Sorry about that. I overlooked that. Updated.
This pull request introduces 1 alert when merging ecf1d7e into 41f9f22 - view on LGTM.com new alerts:
|
@@ -270,7 +270,8 @@ export class FileConfigPage extends ImportPage { | |||
let connectionUri = await azdata.connection.getUriForConnection(this.model.server.connectionId); | |||
let queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>(this.model.server.providerName, azdata.DataProviderType.QueryProvider); | |||
|
|||
let query = `SELECT name FROM sys.schemas`; | |||
const escapedQuotedDb = this.databaseDropdown.value ? (<azdata.CategoryValue>this.databaseDropdown.value).name.replace(/]/g, ']]') + '.' : ''; | |||
const query = 'SELECT name FROM ${escapedQuotedDb}sys.schemas'; |
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 looks like you're using single quotes ( ' ) here instead of backticks ( ` ). You need to use backticks in order for string interpolation to work correctly (otherwise you'll just end up with a string that has ${...} in it)
Also you dropped bracket-quoting the name at some point. I tested this locally and it should work :
const escapedQuotedDb = this.databaseDropdown.value ? `[${(<azdata.CategoryValue>this.databaseDropdown.value).name.replace(/]/g, ']]')}].` : '';
const query = `SELECT name FROM ${escapedQuotedDb}sys.schemas`;
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.
Looks great, thanks for taking the time to fix this and address all the feedback requests!
* Fix for relative links not being resolved in notebook outputs (#7966) * Fix for relative links not being resolved * Add comment * check for ownerDocument focus for focus (#7964) * Update recommended package versions for ps (#7972) * Notebooks: ensure python path dirs added to path on session start (#7968) * ensure python path dirs add to path session start * Change logic slightly * PR feedback from Charles * Fix node infinitely loading when a firewall dialog is cancelled (#7970) * add back icons for azure actions * fix firewall infinite loop * formatting * change message to firewall canceled * fix tests * remove insider build check (#7926) * remove insider build check * fix welcome page not load issue * Fix troubleshoot URL lookup (#7978) * Change BDC view errors to use modal dialog instead of error toast (#7985) * Change BDC view errors to use modal dialog instead of error toast * Move to common control * revert the notebook background execution (#7984) * hide save book action from command pallet (#7981) * make the azdata install url configurable (#7989) * make the azdata install url configurable * use settings without reloading * comments * Use selected DB for import wizard schema list (#7878) * Update fileConfigPage.ts * Update fileConfigPage.ts * Update fileConfigPage.ts * Update fileConfigPage.ts * Update fileConfigPage.ts * Update fileConfigPage.ts * Update fileConfigPage.ts * Update fileConfigPage.ts * Update fileConfigPage.ts * Add SQL Managed Instance support and sorting (#7996) - Add SQL Instances folder and support using existing SQLClient API - Sort subscriptions in tree and quickpick for easier search - Sort all resources (Databases, Servers, Instances) alphabetically too Not in this PR: - Will experiment with Graph API for faster perf & easier addition of other Azure resources such as PostgreSQL * Fix starting and separators in a row (#7861) * Fixes some code coverage issues (#7994) * Fix code coverage issues * Fix some code coverage stuff * builtinExtension-insiders to builtinExtension (#7973) * builtinExtension-insiders to builtinExtension * maintain both insiders and stable. * builtinExtension.js is for build time and skipping the check for dev. * check quality and pick insider vs stable json * Remove RC from strings (#8001) * delete workflow (#8000) * Always send \n instead of \r\n to Jupyter kernel (#7995) * Always send \n instead of \r\n to kernel * Use replace instead of split/join * reclassified autoinstallrequired message to error (#7986) * reclassified autoinstallrequired message to error * Changed level to warning * search book gone from command palette (#8002) * Work with single ext loc file (#7894) * try loc with single file model * adding filter and languages * add links in langpack json * changing variable name and limiting the list to only tested extensions * Fix column text overflow on BDC status pages (#7928) * Fix column text overflow on status page * Fix typo * Fix another typo * suppress the alert (#8007) * Fix Issue when Saving Wrong Kernel (#7974) * Only fire kernelChangeEmitter after lang set * Fix unused import found by lgtm * Fix comment * Fix for Markdown File in Jupyter Books Viewlet not Opening After 2x (#8009) * fix for markdown not opening after opened twice * PR comment to add return type * Adjusting context menu for SqlOnDemand (#8018) * Testing out ci with workflows (#8005) * add workflow for ci * add another step * remove more steps * fix stdin cancel breaks notebook (#8012) * serverManager to decide if server start needed (#8017) * pass install paths to notebooks (#8008) * pass install paths to notebooks * onComplete * discover and publish actual installation Path * pass the path to notebook * minor fixes needed post merge of code from remote * fix some errors * remove unused variable * Don't pack the hgh level node_modules directory (#7998)
Issue #2796 - I added the selected database name to the table schema select statement to pull the accurate table schema list.