Skip to content

AWF JSON-config printf emits unescaped $schema, bash expands to empty key, AWF rejects with config. is not supported #30866

@bryanchen-d

Description

@bryanchen-d

Summary

The compiler-generated lock files write the AWF config via a double-quoted bash printf:

printf '%s\n' "{\"$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.25.40/awf-config.schema.json\",...}" > "${RUNNER_TEMP}/gh-aw/awf-config.json"

Inside bash double quotes, $schema is variable expansion. Since $schema is unset on the runner, it expands to an empty string, so the JSON written to disk becomes:

{ "": "https://github.com/.../awf-config.schema.json", "network": {...}, "apiProxy": {...}, "container": {...} }

AWF v0.25.40 then rejects the config:

Error loading --config: Invalid AWF config at /home/runner/work/_temp/gh-aw/awf-config.json:
- config. is not supported

(Note the trailing dot — the unsupported property is the empty string from the lost $schema key.)

Repro

  1. Compile any agentic workflow with the current gh-aw (v0.71.5 reproduces).
  2. Inspect the generated *.lock.yml — you will see printf '%s\n' "{\"$schema\":\"...\",...}" somewhere in the agent job.
  3. Run the workflow on ubuntu-latest against AWF v0.25.40.
  4. Job fails at startup with the error above.

Affected runs (microsoft/vscode-engineering)

All 6 errors-*.lock.yml workflows broke after gh aw compile regenerated them on 2026-05-06; ~80+ failed runs in the last 24h. Example: https://github.com/microsoft/vscode-engineering/actions/runs/25504792956

Suggested fix

In the AWF-config printf template, either:

  • Escape the dollar sign: \"\$schema\" (bash will write literal $schema), or
  • Use a single-quoted printf payload: printf '%s\n' '{"$schema":"...","..."}' — but this conflicts with ${{ }} expressions if any are inlined. Some lock files (single-quoted variants like errors-fix-driver.lock.yml in our repo) already use this form successfully.
  • Switch to a heredoc with quoted delimiter, like the existing safeoutputs config:
    cat > "${RUNNER_TEMP}/gh-aw/awf-config.json" << 'GH_AW_AWF_CONFIG_EOF'
    {"$schema":"...","network":{...}}
    GH_AW_AWF_CONFIG_EOF
    This is what safeoutputs/config.json already uses in the same lock files and is bullet-proof.

Workaround

Manually sed -i 's|\\"\$schema\\":|\\"\\\$schema\\":|g' each affected *.lock.yml after compile. Overwritten on next compile.

Related

Similar root-cause family to #30307 (config.models is not supported) and to my prior report #30695 (\u0026\u0026 literal in ${{ }}). All three are downstream symptoms of the JSON-emitting layer not accounting for the bash-string context it gets pasted into.

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions