Skip to content

Runtime import resolver does not handle repo-root-absolute paths (leading /) #24896

Description

@bbonafed

Summary

PR #24501 fixed repo-root-relative path resolution in the compile-time ResolveIncludePath (pkg/parser/remote_fetch.go), but the runtime import resolver (actions/setup/js/runtime_import.cjs) was not updated to match. Paths like /.agents/skills/my-skill/instructions.md resolve correctly at compile time but fail at runtime with:

ERR_API: Failed to process runtime import for /.agents/skills/my-skill/instructions.md:
ERR_SYSTEM: Runtime import file not found: /home/runner/work/<repo>/<repo>/.github/workflows/.agents/skills/my-skill/instructions.md

The runtime handler prepends .github/workflows/ to the path instead of resolving from the repo root.

Root Cause

In actions/setup/js/runtime_import.cjs, processRuntimeImport (line ~739) has three branches for path resolution:

  1. Starts with .agents/ → resolve from GITHUB_WORKSPACE (repo root)
  2. Starts with .github/ → strip prefix, resolve under $WORKSPACE/.github
  3. Anything else → prepend workflows/, resolve under $WORKSPACE/.github

A path like /.agents/skills/my-skill/instructions.md has a leading /, so it does NOT match startsWith(".agents/"). It falls into branch 3, producing .github/workflows/.agents/skills/my-skill/instructions.md.

The compile-time resolver (remote_fetch.go) handles this correctly by stripping the leading / before the prefix checks — but the runtime resolver never got the equivalent fix.

Reproduction

  1. Place agent skill files in .agents/skills/ at the repo root
  2. In a workflow .md file, use:
    imports:
      - /.agents/skills/my-skill/instructions.md
  3. Compile with gh aw compile — succeeds, skill content is inlined
  4. The compiled .lock.yml contains {{#runtime-import /.agents/skills/my-skill/instructions.md}}
  5. When the workflow runs on GitHub Actions, the runtime import fails with the error above

gh-aw version: v0.67.1

Proposed Fix

In actions/setup/js/runtime_import.cjs, add a leading-/ strip before the existing prefix checks (around line 749):

// Strip leading "/" for repo-root-absolute paths (e.g. /.agents/skills/..., /.github/agents/...).
// After stripping, the existing .agents/ and .github/ prefix checks handle resolution correctly.
if (filepath.startsWith("/")) {
  const stripped = filepath.substring(1);
  if (stripped.startsWith(".agents/") || stripped.startsWith(".agents\\") ||
      stripped.startsWith(".github/") || stripped.startsWith(".github\\")) {
    filepath = stripped;
  }
}

This mirrors the behavior of ResolveIncludePath in pkg/parser/remote_fetch.go (lines 160-170) which was fixed in PR #24501. If the stripped path doesn't start with .agents/ or .github/, it falls through unchanged to the existing default branch — maintaining the same security restrictions.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions