Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 26, 2025

Adds path field to firewall config, allowing users to specify custom AWF binaries instead of downloading from GitHub releases. Useful for self-hosted runners with pre-installed AWF or custom builds.

Changes

  • Data structure: Added Path field to FirewallConfig struct
  • Schema: Added path property to firewall object in JSON schema
  • Path resolution: Absolute paths used as-is; relative paths resolve to ${GITHUB_WORKSPACE}/
  • Installation logic: When path specified, generates validation step instead of download step
  • Execution: Custom binary path used in AWF command wrapper
  • Security: All paths shell-escaped and normalized via filepath.Clean()

Usage

network:
  firewall:
    path: /usr/local/bin/awf-custom  # absolute
    # or: bin/awf                    # relative → ${GITHUB_WORKSPACE}/bin/awf
  allowed:
    - defaults

When path is set:

  • AWF download is skipped
  • Validation step checks binary exists and is executable
  • version field is ignored

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/user
    • Triggering command: /usr/bin/gh gh api user --jq .login (http block)

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

Original prompt

you are tasked to support custom awf installation path in agentic workflow frontmatter configurations, allowing users to bypass the default GitHub release download mechanism and use their own AWF binaries.

Recommended Approach

User-Facing Syntax

network:
  allowed:
    - defaults
    - node
  firewall:
    path: /custom/path/to/awf  # Absolute or relative path
    log-level: info

Path resolution rules:

  • Paths starting with / are treated as absolute paths
  • Other paths are treated as relative to ${GITHUB_WORKSPACE} (repository root)
  • When path is specified, AWF download is skipped
  • The version field is ignored when path is provided

Implementation Steps

1. Data Structure Changes

File: pkg/workflow/firewall.go (line ~16)

Add Path field to FirewallConfig struct:

type FirewallConfig struct {
    Enabled       bool     `yaml:"enabled,omitempty"`
    Version       string   `yaml:"version,omitempty"`
    Args          []string `yaml:"args,omitempty"`
    LogLevel      string   `yaml:"log_level,omitempty"`
    CleanupScript string   `yaml:"cleanup_script,omitempty"`
    Path          string   `yaml:"path,omitempty"`  // NEW: Custom AWF binary path
}

2. Schema Updates

File: pkg/parser/schemas/main_workflow_schema.json (line ~1670)

Add path property to firewall object schema:

"path": {
  "type": "string",
  "description": "Custom path to AWF binary. When specified, skips downloading AWF from GitHub releases. Supports absolute paths or paths relative to GITHUB_WORKSPACE."
}

3. Frontmatter Extraction

File: pkg/workflow/frontmatter_extraction.go (after line 686)

Add path extraction in extractFirewallConfig:

// Extract path if present
if path, hasPath := firewallObj["path"]; hasPath {
    if pathStr, ok := path.(string); ok {
        config.Path = pathStr
    }
}

4. Core Logic Changes

File: pkg/workflow/copilot_engine.go

4.1 Modify GetInstallationSteps (lines 64-76)

Change from unconditional AWF installation to conditional:

// Add AWF installation or validation steps
if isFirewallEnabled(workflowData) {
    firewallConfig := getFirewallConfig(workflowData)

    if firewallConfig == nil || firewallConfig.Path == "" {
        // Default: Download and install AWF from GitHub releases
        var awfVersion string
        if firewallConfig != nil {
            awfVersion = firewallConfig.Version
        }
        awfInstall := generateAWFInstallationStep(awfVersion)
        steps = append(steps, awfInstall)
    } else {
        // Custom path: Validate the binary exists and is executable
        validationStep := generateAWFPathValidationStep(firewallConfig.Path)
        steps = append(steps, validationStep)
    }
}

4.2 Add New Helper Functions (after line 867)

Function: generateAWFPathValidationStep

Creates a validation step to verify custom AWF binary:

func generateAWFPathValidationStep(customPath string) GitHubActionStep {
    resolvedPath := resolveAWFPath(customPath)

    stepLines := []string{
        "      - name: Validate custom AWF binary",
        "        run: |",
        fmt.Sprintf("          echo \"Validating custom AWF binary at: %s\"", resolvedPath),
        fmt.Sprintf("          if [ ! -f %s ]; then", shellEscapeArg(resolvedPath)),
        fmt.Sprintf("            echo \"Error: AWF binary not found at %s\"", resolvedPath),
        "            exit 1",
        "          fi",
        fmt.Sprintf("          if [ ! -x %s ]; then", shellEscapeArg(resolvedPath)),
        fmt.Sprintf("            echo \"Error: AWF binary at %s is not executable\"", resolvedPath),
        "            exit 1",
        "          fi",
        fmt.Sprintf("          %s --version", shellEscapeArg(resolvedPath)),
    }

    return GitHubActionStep(stepLines)
}

Function: resolveAWFPath

Handles path resolution for absolute and relative paths:

func resolveAWFPath(customPath string) string {
    if customPath == "" {
        return "/usr/local/bin/awf"
    }

    if strings.HasPrefix(customPath, "/") {
        return customPath  // Absolute path
    }

    // Relative path - resolve against GITHUB_WORKSPACE
    return fmt.Sprintf("${GITHUB_WORKSPACE}/%s", customPath)
}

Function: getAWFBinaryPath

Returns appropriate AWF binary path for execution:

func getAWFBinaryPath(firewallConfig *FirewallConfig) string {
    if firewallConfig != nil && firewallConfig.Path != "" {
        return resolveAWFPath(firewallConfig.Path)
    }
    return "awf"  // Default (in PATH from installation step)
}

4.3 Update GetExecutionSteps (line 256)

Change from hardcoded awf to dynamic path:

// Get AWF binary path (custom or default)
awfBinary := getAWFBinaryPath(firewallConfig)

// Build AWF command
command = fmt.Sprintf(`set -o pipefail
sudo -E %s %s \
  -- %s \
  2>&1 | tee %s`,
  shellEscapeArg(awfBinary),
  shellJoinA...

</details>



<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

Copilot AI changed the title [WIP] Support custom AWF installation path in configurations Add support for custom AWF installation path in firewall configuration Nov 26, 2025
Copilot AI requested a review from Mossaka November 26, 2025 19:42
Copilot finished work on behalf of Mossaka November 26, 2025 19:42
@Mossaka
Copy link
Collaborator

Mossaka commented Nov 26, 2025

I'll test this out in gh-aw-firewall

Copilot AI and others added 3 commits November 28, 2025 00:24
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>

# Conflicts:
#	docs/src/content/docs/reference/frontmatter-full.md
#	docs/src/content/docs/reference/network.md
#	pkg/workflow/copilot_engine.go
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
@Mossaka Mossaka force-pushed the copilot/support-custom-awf-path branch from 0c41f8a to 680093a Compare November 28, 2025 00:31
@Mossaka Mossaka marked this pull request as ready for review November 28, 2025 00:31
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.

2 participants