Conversation
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
…improved error handling
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
…acDeploymentOnMachineGroupV0
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
…loymentOnMachineGroupV0
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
Revert splatting/ConvertTo-SqlCmdParameterHashtable approach and instead apply Protect-ScriptArguments from Common/Sanitizer module, matching the pattern used by AzureFileCopyV5/V6 and other tasks. - Import Sanitizer module in DeploySqlAzure.ps1 and Main.ps1 - Sanitize sqlcmdAdditionalArguments, sqlcmdInlineAdditionalArguments, and sqlpackageAdditionalArguments when AZP_75787 FF is active - Add Sanitizer to make.json for both tasks - Bump versions to 1.273.0 / 0.273.0 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: 3 pipeline(s) require an authorized user to comment /azp run to run. |
|
Azure Pipelines: 3 pipeline(s) require an authorized user to comment /azp run to run. |
…qlDacpacDeployment tasks
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
1 similar comment
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
/azp run |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
Azure Pipelines: Successfully started running 3 pipeline(s). |
|
|
||
| if ($deploymentAction -eq "DriftReport" -and $LASTEXITCODE -eq 1) { | ||
| $errorMessage += Get-VstsLocString -Key "SAD_DriftReportWarning" | ||
| $errorMessage += " " + (Get-VstsLocString -Key "SAD_DriftReportWarning") |
There was a problem hiding this comment.
Why do we need space at the beginning here?
There was a problem hiding this comment.
Because there is a link ending in the error message to which this part is appended to. And the URL is broken then.
https://aka.ms/ado/75787
vs
https://aka.ms/ado/75787Check
I noticed it and decided to fix it.
It goes like this (bolded part is where separation is added):
##[error]SECURITY ERROR: Failed to sanitize SQL arguments. Task cannot proceed safely. Error: Detected characters in arguments that may not be executed correctly by the shell. Please escape special characters using backtick (`). More information is available here: https://aka.ms/ado/75787 Check out how to troubleshoot failures at https://aka.ms/sqlazuredeployreadme#troubleshooting-
|
|
||
| function Should-UseSanitizedArguments { | ||
| try { | ||
| $orgLevelEnabled = Get-SanitizerCallStatus |
There was a problem hiding this comment.
Do we want to allow vulnerability if toggle is disabled in organization settings? @manolerazvan you proposed this initially, probably due to option to rollback changes if something goes wrong (or maybe not), but after some thinking not sure whether it's smart to tie security fix with option that allows users to disable it on their own.
In other words, I think it would be best to avoid any disablement by users.
The same question goes for my PR (other security fix), because I used the same approach.
There was a problem hiding this comment.
In order to disable this, you need to be organization admin.
And we try to protect pipelines from user that don't even have permission to edit pipelines, but just to run them and modify their environment variables.
I think this is why we allow this to be toggled on org level.
However, I am happy to hear insights from Razvan on this topic, as I don't have prior experience with such issues.
| Describe "Execute-Command Security Tests" { | ||
| Context "AST Parser Validation" { | ||
| It "Should use token .Value instead of .Text" { | ||
| # This test verifies the fix for Ivan's concern about quote handling |
There was a problem hiding this comment.
Ivan's concern won't be clear once PR is merged. Lets be clear about use case
| @@ -0,0 +1,129 @@ | |||
| # Unit tests for SQL argument sanitization security functions | |||
| [CmdletBinding()] | |||
There was a problem hiding this comment.
Is it possible to mock the feature flags and invoke Get-SanitizedSqlArguments with malicious input to verify such inputs are blocked?
| $additionalArguments = EscapeSpecialChars $additionalArguments | ||
|
|
||
| #Execute the query | ||
| Invoke-Expression "Invoke-SqlCmd @spaltArguments $additionalArguments" |
There was a problem hiding this comment.
The Invoke-SqlScriptsInTransaction function still executes:
Invoke-Expression "Invoke-SqlCmd @spaltArguments $additionalArguments"
I understand that $additionalArguments is sanitized upstream before it reaches this function, so today all callers pass clean input.
However, this is a public function that could be called from other entry points in the future without the sanitization gate. Compare with what was done for Execute-Command in V1 task — there, the Invoke-Expression was replaced entirely with AST-parsed array-based invocation (& $FileName $argArray), eliminating the dangerous pattern at the sink itself regardless of whether the caller sanitized.
The same treatment would be straightforward here since the function already uses splatting (@spaltArguments) for most parameters — the $additionalArguments string just needs to be parsed and merged into the splat hashtable (or passed as an array) instead of being concatenated into an Invoke-Expression string.
Not a blocker for this PR since all current callers pass sanitized input, but worth considering as a follow-up hardening pass to fully eliminate the Invoke-Expression pattern from both tasks.
Context
This PR addresses a critical security vulnerability in SqlAzureDacpacDeploymentV1 and SqlDacpacDeploymentOnMachineGroupV0 tasks that allows arbitrary PowerShell command injection through the
SqlAdditionalArgumentsparameter.Task Name
SqlAzureDacpacDeploymentV1, SqlDacpacDeploymentOnMachineGroupV0
Description
1. Safe Argument Execution
Invoke-Expressionwith string concatenation2. Dual Feature Flag Gating
Sanitization activates only when both flags are enabled:
AZP_75787environment variableEnableSqlAdditionalArgumentsSanitizationpipeline variableThis allows gradual rollout and testing without breaking existing pipelines.
3. Sanitization Layer
Sanitizercommon moduleProtect-ScriptArgumentsto validate and sanitize SQL arguments4. Telemetry
Added telemetry tracking for:
5. Backward Compatibility
Get-VstsPipelineFeaturecmdletChanges
SqlAzureDacpacDeploymentV1 (v1.273.6):
Execute-Commandto use AST Parser instead ofInvoke-ExpressionShould-UseSanitizedArgumentswith dual feature flag checksGet-SanitizedSqlArgumentswith fail-closed validationSqlDacpacDeploymentOnMachineGroupV0 (v0.273.4):
Risk Assessment (Low / Medium / High)
Medium. Needs rollout monitoring not to break this task and introduce regression. Such monitors are already in place. But we should monitor telemetry emitted from this task too (there is newly added telemetry).
Change Behind Feature Flag (Yes / No)
Sanitization activates only when BOTH flags are enabled:
Enable shell tasks arguments validationin organisation settingsEnableSqlAdditionalArgumentsSanitization(dynamic FF), can be used as DISTRIBUTED_TASK_EnableSqlAdditionalArgumentsSanitization evnironment variableThis allows gradual rollout and testing before full enforcement.
Tech Design / Approach
/
Documentation Changes Required (Yes/No)
Probably.
Unit Tests Added or Updated (Yes / No)
Added some tests.
Additional Testing Performed
Manual testing.
Logging Added/Updated (Yes/No)
No.
Telemetry Added/Updated (Yes/No)
No.
Rollback Scenario and Process (Yes/No)
Dependency Impact Assessed and Regression Tested (Yes/No)
No.
Checklist