github / github/gh-aw

Feature: parameterize tools availability and allowlists for reusable workflows

Open
#29,189 0 comments 1 reaction 2 assignees Claimed by @pelikhan View on GitHub
ai-inspected community
Dominant language
Go
Stars
5.1k
Forks
541
Avg merge
5h 46m
Merged PRs (30d)
760

Description

## Problem

Reusable `workflow_call` agentic workflows can parameterize some tool-related values today, such as `tools.timeout` and `tools.startup-timeout`, but the actual tools and tool allowlists remain compile-time-only.

This makes reusable workflows hard to compose when callers need to choose between otherwise-similar tool policies. For example, callers may want to select a Bash command allowlist, GitHub MCP toolsets, or whether an editing tool is enabled without maintaining separate workflow files for each tool configuration.

Representative examples that are not currently supported:

```yaml
on:
workflow_call:
inputs:
bash-tools:
type: string
github-toolsets:
type: string
---
tools:
bash: ${{ inputs.bash-tools }}
github:
toolsets: ${{ inputs.github-toolsets }}
```

Related context: #23724 confirmed appetite for parameterizing frontmatter fields other than `engine.id`. Follow-up work covered `timeout-minutes`, `engine.version`, and tool timeout fields, but not tool availability or tool allowlists.

## Desired Behavior

Reusable workflows should be able to expose selected tool policy inputs while preserving least privilege and fail-closed behavior.

Possible authoring pattern:

```yaml
on:
workflow_call:
inputs:
bash-allowlist:
type: string
description: JSON array or newline/comma-separated command allowlist
github-toolsets:
type: string
description: JSON array or newline/comma-separated GitHub MCP toolsets
---
tools:
bash: ${{ inputs.bash-allowlist }}
github:
toolsets: ${{ inputs.github-toolsets }}
```

Literal static config must remain valid:

```yaml
tools:
bash: ["bash", "git", "gh"]
edit:
github:
toolsets: [repos, issues]
```

## Security Model

Because tools directly affect what an agent can do, expression support should not silently widen privileges.

A conservative implementation would be acceptable, for example:

- Require workflow authors to declare a compile-time maximum/superset of allowed tools.
- Let runtime inputs select a subset of that declared superset.
- Validate runtime-resolved values before enabling tools.
- Fail closed when an expression resolves to an invalid command/tool/toolset.
- Avoid expression support for fields that would require adding broader GitHub permissions at runtime unless the compiled workflow already includes the needed least-privilege permissions safely.

## Proposed Scope

Start with fields that are high-value for reusable workflows and can be validated against known allowlists:

- `tools.bash` command allowlist
- `tools.edit` enable/disable if this can be expressed without changing job permissions unsafely
- `tools.github.toolsets`
- `tools.github.allowed` / `tools.github.blocked` if those are the current precise allowlist controls
- Any shared parsing helpers for string-list tool config

This issue intentionally excludes `engine.id`, which is a separate architectural question already called out in #23724.

## Implementation Plan

Please implement this as an agentic-plan contribution rather than a direct community PR.

1. **Audit tool config shape**
- Inspect `pkg/parser/schemas/main_workflow_schema.json` tool definitions and Go parsing under `pkg/workflow`.
- Identify which tool fields influence generated jobs, generated permissions, MCP server config, or runtime handler config.
- Classify fields as safe for expression support, safe only with compile-time superset validation, or not appropriate for runtime parameterization.

2. **Choose runtime list format**
- Reuse an existing convention where possible, such as JSON array, comma-separated string, newline-separated string, or the flexible list parser used by GitHub guard-policy fields.
- Document the chosen format for `workflow_call` inputs.

3. **Schema updates**
- Allow selected fields to accept either their current literal types or a GitHub Actions expression string.
- Keep item-level validation for literal arrays.
- Keep non-expression strings invalid unless a field already intentionally accepts scalar strings.

4. **Parser/config updates**
- Preserve expression strings distinctly from literal arrays or booleans.
- Add or reuse templatable string-list helpers for tool allowlists.
- For fields with a compile-time superset model, validate that literal supersets are present and that runtime selections cannot exceed them.

5. **Compilation/runtime validation**
- Ensure expression values are emitted so GitHub Actions can evaluate them at runtime.
- Validate runtime-resolved values before starting tool servers or handing capabilities to the agent.
- Fail closed on malformed values or values outside the allowed superset.
- Avoid direct shell interpolation of expression-resolved values.

6. **Tests**
- Add schema/parser tests for literal values, expression values, invalid literal values, and invalid expression-resolved values.
- Add compiler tests proving expressions are preserved in generated lock YAML in runtime-evaluable locations.
- Add runtime tests for fail-closed validation of command/toolset selections.

7. **Documentation**
- Update the tools reference with reusable `workflow_call` examples.
- Clearly document any compile-time superset requirement and runtime input format.
- Explain which tool fields support expressions and which remain compile-time by design.

## Acceptance Criteria

- [ ] Selected `tools` fields accept GitHub Actions expression strings in reusable workflows.
- [ ] Literal tool configs remain backward compatible.
- [ ] Runtime-resolved tool selections are validated before use.
- [ ] Runtime inputs cannot silently expand beyond the workflow author's declared security boundary.
- [ ] Invalid or malformed resolved values fail closed with clear errors.
- [ ] Tests and documentation are updated.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.