Skip to content

[safeoutputs] Improve upload_artifact path Description to Prevent Shell Variable Confusion #26521

@github-actions

Description

@github-actions

Summary

Analysis of the last 24 hours of workflow runs (150 runs) identified 1 error where an agent incorrectly used the upload_artifact safe output tool. The workflow prompt for the affected run appears correctly written, indicating the tool description needs improvement to prevent this class of error.

🔍 Error Analysis Details

Error Pattern: Agent Uses Literal $RUNNER_TEMP in Path

Occurrences: 1 time (workflow: Daily Project Performance Summary Generator (Using MCP Scripts))

What the agent did wrong:

Provided $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/activity_overview.png as the path value — a shell variable reference that is never expanded when it appears in a JSON string.

Actual safe output emitted (Run §24483658715):

{"integrity":"high","path":"$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/activity_overview.png","secrecy":"public","temporary_id":"aw_act1","type":"upload_artifact"}
```

**Validation error**:
```
ERR_VALIDATION: upload_artifact: path does not exist in staging directory:
$RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/activity_overview.png.
Available files: [activity_overview.png, resolution_metrics.png, velocity_metrics.png]

Expected (correct value):

{"path": "activity_overview.png", "type": "upload_artifact", "temporary_id": "aw_act1"}

How the error happened:

  1. The workflow prompt's Phase 4 instructed the agent to copy chart files to the staging directory:
    cp /tmp/gh-aw/python/charts/activity_overview.png $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/
  2. When the agent then called upload_artifact, it naturally combined the staging destination from step 1 with the filename — producing $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/activity_overview.png.
  3. But shell variables like $RUNNER_TEMP are never expanded inside JSON string values. The validator received this as a literal relative path, looked for a file named $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/activity_overview.png inside the staging directory, and failed.

Current Tool Description

Current path field description (pkg/workflow/js/safe_outputs_tools.json)
{
  "name": "upload_artifact",
  "description": "Upload files as a run-scoped GitHub Actions artifact. Files can be pre-staged in $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/ or referenced by their original path — files not already in the staging directory are automatically copied there before upload. Absolute paths and paths relative to the workspace are supported. ...",
  "inputSchema": {
    "properties": {
      "path": {
        "type": "string",
        "description": "Path to the file or directory to upload. Can be relative to $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/, an absolute path, or a path relative to the workspace. Files not already in the staging directory are automatically copied there. Required unless filters is provided."
      }
    }
  }
}

Root Cause Analysis

The tool description has two problems that lead agents to use $RUNNER_TEMP as a literal string in JSON:

  1. Misleading phrase: "Can be relative to $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/" — agents read this as "you may use $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/ as a path prefix", when the intent is "you may use just the filename, and it will resolve against the staging directory".

  2. No warning about shell variables: The description mentions $RUNNER_TEMP in the path field without clarifying that shell variable references are never expanded inside JSON string values. This is a common source of confusion across all AI engines.

Recommended Improvements

1. Update path field description

Current:

"Path to the file or directory to upload. Can be relative to $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/, an absolute path, or a path relative to the workspace. Files not already in the staging directory are automatically copied there. Required unless filters is provided."

Suggested:

"Path to the file or directory to upload. Three formats are accepted: (1) filename only (e.g., \"chart.png\") — resolved relative to the upload staging directory; use this when the file was already copied there. (2) absolute path (e.g., \"/tmp/gh-aw/charts/chart.png\") — the file is automatically copied from disk into the staging directory. (3) workspace-relative path (e.g., \"reports/summary.json\") — resolved from the workspace root. ⚠️ Do NOT use shell variable syntax like $RUNNER_TEMP/... — shell variables are not expanded inside JSON string values. Required unless filters is provided."

2. Update top-level description

Replace the sentence "Files can be pre-staged in $RUNNER_TEMP/gh-aw/safeoutputs/upload-artifacts/ or referenced by their original path" with something like:

"Files can be referenced by their original absolute path (auto-copied into the staging area) or by a short relative filename if already staged. Shell variable references like $RUNNER_TEMP must NOT appear in the path value — they are not expanded in JSON."

3. Add a concrete example

Consider adding an examples field or expanding the description with a side-by-side:

# File already in staging directory:
"path": "activity_overview.png"       ✅ correct
"path": "$RUNNER_TEMP/.../activity_overview.png"  ❌ wrong — $RUNNER_TEMP not expanded

# File at original path:
"path": "/tmp/gh-aw/python/charts/activity_overview.png"  ✅ auto-copied to staging

Affected Workflows

The following workflow had the error:

  • daily-project-performance-summary-generator-using-mcp-scripts — 1 error (all 3 upload_artifact calls failed with same pattern, max-uploads policy allowed only 1 attempt to be reported)

Implementation Checklist

  • Update path field description in pkg/workflow/js/safe_outputs_tools.json
  • Update top-level description of upload_artifact tool to remove $RUNNER_TEMP staging path reference
  • Run make build to rebuild binary
  • Run make recompile to update all compiled workflows
  • Run make test to ensure no regressions
  • Monitor daily-project-performance-summary-generator-using-mcp-scripts runs for 2–3 days to confirm error rate drops

References

  • Tool schema: pkg/workflow/js/safe_outputs_tools.json
  • Handler: actions/setup/js/upload_artifact.cjs (see resolveFiles function, lines 294–340)
  • MCP server loader: actions/setup/js/safe_outputs_tools_loader.cjs

Run IDs with errors: §24483658715

Generated by Daily Safe Output Tool Optimizer · ● 473.6K ·

  • expires on Apr 17, 2026, 11:57 PM UTC

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