Skip to content

fix: allow expr || 'literal' default patterns in expression validation#19550

Merged
pelikhan merged 4 commits intomainfrom
copilot/allow-simple-defaults-in-expressions
Mar 4, 2026
Merged

fix: allow expr || 'literal' default patterns in expression validation#19550
pelikhan merged 4 commits intomainfrom
copilot/allow-simple-defaults-in-expressions

Conversation

Copy link
Contributor

Copilot AI commented Mar 4, 2026

Expression validation rejected valid default-value patterns like ${{ inputs.devices || 'mobile,tablet,desktop' }} because the parser correctly decomposed the OrNode into leaf nodes, then validated each leaf independently — causing string literals to fail the allowlist check.

Changes

  • expression_validation.go: Add early-return literal check at the top of validateSingleExpression — string ('...', "...", `...`), number, and boolean literals are unconditionally allowed since they are safe constants
  • expression_validation.go: Promote the inline literal-detection regexes to pre-compiled package-level vars (stringLiteralRegex, numberLiteralRegex) used by both the new literal check and the existing OR fallback path

Example

These patterns now compile successfully:

- **Repository**: ${{ github.repository }}
- **Run ID**: ${{ github.run_id }}
- **Triggered by**: @${{ github.actor }}
- **Devices to test**: ${{ inputs.devices || 'mobile,tablet,desktop' }}
- **Docs directory**: ${{ inputs.docs_dir || 'docs' }}
- **Build command**: ${{ inputs.build_command || 'npm run build' }}
- **Serve command**: ${{ inputs.serve_command || 'npm run preview' }}
- **Server port**: ${{ inputs.server_port || '4321' }}
- **Working directory**: ${{ github.workspace }}

Unauthorized left-hand sides are still rejected — ${{ secrets.TOKEN || 'fallback' }} continues to fail.

Tests

Added comprehensive tests in TestValidateExpressionSafetyWithParser covering:

  • String, number (|| 30), and boolean (|| false, || true) literal defaults
  • All allowed context types with defaults: inputs.*, github.event.inputs.*, github.*, steps.*, needs.*, env.*
  • Single-quoted and double-quoted string defaults
  • The full example from the issue as an end-to-end test case
Original prompt

This section details on the original issue you should resolve

<issue_title>Allowed expressions should allow simple defaults</issue_title>
<issue_description>A generated workflow used a nice pattern to embed defaults reliably:

- **Repository**: ${{ github.repository }}
- **Run ID**: ${{ github.run_id }}
- **Triggered by**: @${{ github.actor }}
- **Devices to test**: ${{ inputs.devices || 'mobile,tablet,desktop' }}
- **Docs directory**: ${{ inputs.docs_dir || 'docs' }}
- **Build command**: ${{ inputs.build_command || 'npm run build' }}
- **Serve command**: ${{ inputs.serve_command || 'npm run preview' }}
- **Server port**: ${{ inputs.server_port || '4321' }}
- **Working directory**: ${{ github.workspace }}

This seems valid to allow - a || b for two valid expressions including simple constants
</issue_description>

Comments on the Issue (you are @copilot in this section)

@pelikhan This should be allowed for expressions that are controlled by github. @pelikhan Add tests

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Allow expressions to utilize simple defaults fix: allow expr || 'literal' default patterns in expression validation Mar 4, 2026
@pelikhan
Copy link
Contributor

pelikhan commented Mar 4, 2026

@copilot add more tests

…ontext types)

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 4, 2026

@copilot add more tests

Added more tests in c3f87d4, covering:

  • Number literal defaults (inputs.timeout || 30)
  • Boolean defaults (inputs.debug || false, inputs.enabled || true)
  • All allowed context types with defaults: github.*, steps.*, needs.*, env.*
  • Double-quoted string defaults
  • The full example from the issue as a single test case

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha rite &#39;../../../**/*.json&#39; &#39;!../../../pkg/workflow/js/**/*.json&#39; --ignore-path /tmp/go-build1004626149/b199/vet.cfg /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha */*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.prettierignore 4626149/b223/vet.cfg h http.https://gitgit (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha npx prettier --write &#39;**/*.cjs&#39; &#39;**/*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.pr**/*.json -tests /home/REDACTED/node_modules/.bin/node (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha xterm-color x_amd64/vet /usr/bin/gh (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha rite &#39;**/*.cjs&#39; &#39;**/*.ts&#39; &#39;**/*.json&#39; --ignore-path ../../../.prettierignore /tmp/go-build1004626149/b010/vet.cfg k/_temp/uv-python-dir/node (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha -unreachable=false /tmp/go-build1004626149/b139/vet.cfg ache/node/24.13.1/x64/bin/npm (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq .object.sha --show-toplevel x_amd64/vet /usr/bin/git ath ../../../.prgit (http block)
  • https://api.github.com/repos/actions/download-artifact/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/download-artifact/git/ref/tags/v8 --jq .object.sha js/**/*.json&#39; --ignore-path ../../../.prettierignore (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/download-artifact/git/ref/tags/v8 --jq .object.sha json&#39; --ignore-path ../../../.pr**/*.json .cfg 64/pkg/tool/linux_amd64/vet hub.com/.extrahegit (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/download-artifact/git/ref/tags/v8 --jq .object.sha (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -unreachable=false /tmp/go-build1004626149/b065/vet.cfg 4626149/b247/vet.cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha -unreachable=false /tmp/go-build1004626149/b085/vet.cfg .cfg (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha --show-toplevel x_amd64/vet (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha -unreachable=false /tmp/go-build1004626149/b052/vet.cfg ache/go/1.25.0/x64/bin/node (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha /tmp/go-build1004626149/b075/_pkg_.a -trimpath cal/bin/node -p testing/internalrev-parse -lang=go1.25 erignore m/_n�� -bool -buildtags ache/go/1.25.0/x64/bin/go -errorsas r -nilfunc /opt/hostedtoolcache/go/1.25.0/x64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha re --log-level=e!../../../pkg/workflow/js/**/*.json (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha w/js/**/*.json&#39; --ignore-path (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha ignore-path ../../../.prettierignore (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha ignore-path ../../../.prettierignore (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@pelikhan pelikhan marked this pull request as ready for review March 4, 2026 09:05
Copilot AI review requested due to automatic review settings March 4, 2026 09:05
@pelikhan pelikhan merged commit 0ec30e5 into main Mar 4, 2026
47 checks passed
@pelikhan pelikhan deleted the copilot/allow-simple-defaults-in-expressions branch March 4, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allowed expressions should allow simple defaults

2 participants