Skip to content

Emit an error diagnostic when a secure output is dereferenced indirectly#17453

Merged
jeskew merged 3 commits into
mainfrom
jeskew/16992
Jul 23, 2025
Merged

Emit an error diagnostic when a secure output is dereferenced indirectly#17453
jeskew merged 3 commits into
mainfrom
jeskew/16992

Conversation

@jeskew
Copy link
Copy Markdown
Contributor

@jeskew jeskew commented Jun 24, 2025

Resolves #16992

Indirect references to module outputs don't support compilation to the listOutputsWithSecureValues function due to a combination of limitations in the compiler and the backend. This PR adds an error diagnostic to expressions that will cause a deployment error today.

Microsoft Reviewers: Open in CodeFlow

@jeskew jeskew requested review from a team and Copilot June 24, 2025 15:49
Copy link
Copy Markdown

Copilot AI left a 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 introduces error diagnostics for indirect secure output accesses to block unsupported module output dereferences. Key changes include updating type resolution for module unions, adding new abstract members to syntax classes for property/array access, and implementing a new diagnostic in the emit limitation calculation along with corresponding integration tests.

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Bicep.Core/TypeSystem/TypeHelper.cs Added union type handling logic to resolve secure module output accesses
src/Bicep.Core/Syntax/PropertyAccessSyntax.cs Overrode IndexExpression to point to the property name
src/Bicep.Core/Syntax/ArrayAccessSyntax.cs Updated IndexExpression to override the base definition
src/Bicep.Core/Syntax/AccessExpressionSyntax.cs Introduced an abstract IndexExpression property
src/Bicep.Core/Emit/EmitLimitationCalculator.cs Added logic to block indirectly referenced secure output accesses
src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs Added a new diagnostic for secure outputs accessed via indirect module ref
src/Bicep.Core.IntegrationTests/SecureOutputsTests.cs Added tests to verify that indirect secure output references are blocked

Comment thread src/Bicep.Core/TypeSystem/TypeHelper.cs Outdated
Comment on lines +186 to +187
null when unionType.Members.All(t => t.Type is ModuleType) &&
CreateTypeUnion(unionType.Members.Select(t => ((ModuleType)t.Type).Body)) is UnionType bodyUnion
Copy link

Copilot AI Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider extracting the complex null pattern condition into a helper method for improved readability and maintainability.

Suggested change
null when unionType.Members.All(t => t.Type is ModuleType) &&
CreateTypeUnion(unionType.Members.Select(t => ((ModuleType)t.Type).Body)) is UnionType bodyUnion
null when IsModuleTypeUnionWithBody(unionType, out var bodyUnion)

Copilot uses AI. Check for mistakes.
continue;
}

diagnostics.Write(DiagnosticBuilder.ForPosition(accessExpr.IndexExpression)
Copy link

Copilot AI Jun 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The condition chain in BlockSecureOutputAccessOnIndirectReference is complex; consider refactoring nested checks into separate helper methods to enhance clarity and ease of future modifications.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 24, 2025

Test this change out locally with the following install scripts (Action run 16469365259)

VSCode
  • Mac/Linux
    bash <(curl -Ls https://aka.ms/bicep/nightly-vsix.sh) --run-id 16469365259
  • Windows
    iex "& { $(irm https://aka.ms/bicep/nightly-vsix.ps1) } -RunId 16469365259"
Azure CLI
  • Mac/Linux
    bash <(curl -Ls https://aka.ms/bicep/nightly-cli.sh) --run-id 16469365259
  • Windows
    iex "& { $(irm https://aka.ms/bicep/nightly-cli.ps1) } -RunId 16469365259"

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 24, 2025

Dotnet Test Results

    90 files   -     45      90 suites   - 45   37m 55s ⏱️ - 24m 48s
12 195 tests  -     11  12 195 ✅  -     11  0 💤 ±0  0 ❌ ±0 
28 195 runs   - 14 089  28 195 ✅  - 14 089  0 💤 ±0  0 ❌ ±0 

Results for commit e7cb98d. ± Comparison against base commit eb21df0.

This pull request removes 1910 and adds 646 tests. Note that renamed tests count towards both.

		nestedProp1: 1
		nestedProp2: 2
		prop1: true
		prop2: false
	1
	2
	\$'")
	prop1: true
	prop2: false
…
Bicep.Core.IntegrationTests.AzTypesViaRegistryTests ‑ Bicep_compiler_handles_corrupted_extension_package_gracefully (\u001f�\u0008\u0000\u0000\u0000\u0000\u0000\u0000
�ӽ
�0\u0010\u0000��>E�\u0003�$M�V��"��\u0000�=�bki#\u0004�w7\u001dĥť?���\u001br\u0007�K8��k�\u0005�CӒH�|M�ب\u0013	�{�aB!��(�JJ�\u0010��w���\u001aݸV��\u0007�\u0018kS��2%9\u0017����q"�T+�ˆr,��6紨r���ު��\u001c*_zLo����{�o�OC��t�3�B�h$]Dx��������P��!3��<B\u0013l�I_[x.ݛ�y�7�\u0017g\u0003\u0014�\u0000\u000c\u0000\u0000,"Value cannot be null. (Parameter 'source')")
Bicep.Core.IntegrationTests.AzTypesViaRegistryTests ‑ Bicep_compiler_handles_corrupted_extension_package_gracefully (\u001f�\u0008\u0000\u0000\u0000\u0000\u0000\u0000
��K\u000e�0\u0010\u0006�=EOPf�)e�ޥWh��G(\u0006J$1�ݲ0q\u0001q�`b�e�I��_%;�oK{(�Ve�R��� ȘG�\u0007�Q�y\u0001\u0001Fk\u0010B��w2�k�mB+K���(�֟��@��\u0018\u0008Aq���l��~r\u000e���cѹ��oN���
\u0005�T��\u0007�F��߷��S�\u0001H�����A���İZ.��?����v\u0007Q\u0014E�\u001a�WL��\u0000\u000c\u0000\u0000,"The path: index.json was not found in artifact contents")
Bicep.Core.IntegrationTests.AzTypesViaRegistryTests ‑ Bicep_compiler_handles_corrupted_extension_package_gracefully (\u001f�\u0008\u0000\u0000\u0000\u0000\u0000\u0000
��M\u000b�0\u0018\u0007��\u0014�\u000f0���Y�!�\u0011\u0016\u0004]c���\u0016j �囇�t�%h��\u0007�l�?��u�Nt�\u0014%�\u0004g.A}��'D�z\u0003�B��(�JJ�\u0010�{��ţ�taF\u0019c�\u001f�|��4K\u0002P�1A\u0019(\u0002\y\u000c�����j0�w]]�4���\�[޴g]�S\u001f���y���[�)\u0013\u0008$�\u0001\u0005\u000e�z��<�Q2����:at\n��is�E�\u0002�\u001fx�,˲��\u0000�$�
\u0000\u000c\u0000\u0000,"'7' is an invalid end of a number. Expected a delimiter. Path: $.INVALID_JSON | LineNumber: 0 | BytePositionInLine: 20.")
Bicep.Core.IntegrationTests.AzTypesViaRegistryTests ‑ Bicep_compiler_handles_corrupted_extension_package_gracefully (\u001f�\u0008\u0000\u0000\u0000\u0000\u0000\u0000\u0003�ӽ
�0\u0010\u0007��>E�\u0003�|_+��\u0008.>@lO��*m�����A\,.�
�7d�\u001d���gӕ�\u0016�
lZ���)#C�������@\u0004<p��XN\u0008�\u0006��s�]\u0013F��[?H����¹\u0000#�\u000e�R,S֤`'����DFO���e]`������W}���f�㹿��x���4\u0011&���\u0005 �\u001acC�?��?���&�\u001a�\u0013�\u001e�%V\u001bl�\u0019ݺC��o�\u0016EQ\u0014��\u0006�M"'\u0000\u000c\u0000\u0000,"Value cannot be null. (Parameter 'source')")
Bicep.Core.IntegrationTests.AzTypesViaRegistryTests ‑ Bicep_compiler_handles_corrupted_extension_package_gracefully (\u001f�\u0008\u0000\u0000\u0000\u0000\u0000\u0000\u0003�Խ
�0\u0010\u0007��>E�\u0003��4\u001fV� 8X�*\u0008�\u0012l�
��V(�\uda58\udcf8���C0�19�\u000b�?�۫z�U��\u0012�TH\u000f���!\u0018k=o\u0010&\u0011�o�@r\u0001\u00089ux��*�(c��At�*�tH$���E�8\u0000b�\u0015��ݹ�\u0004�]U�0�\u0013]�ky˛�|�gZ\u001d>�\u001b�Ƿ�\u0003e�p�\u0019\u0005)�D 8�&��d����t����F��氋݅c~�g�,˲��\u0002_��h\u0000\u000c\u0000\u0000,"'7' is an invalid end of a number. Expected a delimiter. Path: $.INVALID_JSON | LineNumber: 0 | BytePositionInLine: 20.")
Bicep.Core.IntegrationTests.AzTypesViaRegistryTests ‑ Bicep_compiler_handles_corrupted_extension_package_gracefully (\u001f�\u0008\u0000\u0000\u0000\u0000\u0000\u0000\u0003���
�0\u000c\u0007�}�=A�dm���=�
E\u0007~�N�\u000e\u0007��\u001d\u0004\u000f\u001b^�&�߱	$%�e��ݶ���ndF�S)�\u0006�Qj��\u0008�\u0017\u0010�Z�\u0010I7�&\u0003���:�2Ǭ\u001fD�X�*�\u001cY\u0013�p�L��\u0006H�Bi?V��j�1o��U7'�M���r���_Fc�/��\u0019��\u000f@\u00025d��
s�?*\u000c��%�����c�
�(��%<\u0001�՗�\u0000\u000c\u0000\u0000,"The path: index.json was not found in artifact contents")
Bicep.Core.IntegrationTests.DirectResourceCollectionTests ‑ DirectResourceCollectionAccess_NotAllowedWithinLoops ("output loopOutput array = [for i in range(0, 2): {
  prop: map(containerWorkers, (w) => w.properties.ipAddress.ip)
}]")
Bicep.Core.IntegrationTests.DirectResourceCollectionTests ‑ DirectResourceCollectionAccess_NotAllowedWithinLoops ("resource propertyLoop 'Microsoft.ContainerInstance/containerGroups@2022-09-01' = {
  name: 'gh9440-loop'
  location: 'westus'
  properties: {
    containers: [for i in range(0, 2): {
      name: 'gh9440-w1c-${i}'
      properties: {
        command: [
          'echo "${join(map(containerWorkers, (w) => w.properties.ipAddress.ip), ',')}"'
        ]
      }
    }]
  }
}")
Bicep.Core.IntegrationTests.DirectResourceCollectionTests ‑ DirectResourceCollectionAccess_NotAllowedWithinLoops ("var loopVar = [for i in range(0, 2): {
  prop: map(containerWorkers, (w) => w.properties.ipAddress.ip)
}]")
Bicep.Core.IntegrationTests.Emit.ParamsFileWriterTests ‑ Params_file_with_no_errors_should_compile_correctly ("
using 'main.bicep'

// involves all syntax
param myParam = {
  arr: [
    {
      a : 'b'
    }
    {
      c : true
    }
  ]
  name: 'complex object!'
  priority: 3
  val: null
  obj: {
      a: 'b'
      c: [
          'd'
           1
      ]
  }
}","
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "myParam": {
      "value": {
        "arr" : [
          {
            "a" : "b"
          },
          {
            "c" : true
          }
        ],
        "name" : "complex object!",
        "priority" : 3,
        "val" : null,
        "obj" : {
          "a" : "b",
          "c" : [
            "d",
            1
          ]
        }
      }
    }
  }
}","
param myParam object
")
…

♻️ This comment has been updated with latest results.

jeskew added 2 commits June 24, 2025 13:16
# Conflicts:
#	src/Bicep.Core/Diagnostics/DiagnosticBuilder.cs
Copy link
Copy Markdown
Member

@majastrz majastrz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@jeskew jeskew merged commit 42d97bb into main Jul 23, 2025
44 checks passed
@jeskew jeskew deleted the jeskew/16992 branch July 23, 2025 11:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Secure output access on mapped collection raises no diagnostic but fails at runtime

3 participants