diff --git a/.github/workflows/security-lint.lock.yml b/.github/workflows/security-lint.lock.yml new file mode 100644 index 0000000000..1983df881a --- /dev/null +++ b/.github/workflows/security-lint.lock.yml @@ -0,0 +1,658 @@ +# +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw. DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# For more information: https://github.com/githubnext/gh-aw/blob/main/.github/aw/github-agentic-workflows.md +# +# Automated security scanning and workflow linting for GitHub Actions + +name: "Security Lint" +"on": + pull_request: + paths: + - .github/workflows/** + push: + branches: + - main + +permissions: + contents: read + +concurrency: + group: "gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" + cancel-in-progress: true + +run-name: "Security Lint" + +jobs: + activation: + needs: pre_activation + if: > + (needs.pre_activation.outputs.activated == 'true') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + comment_id: "" + comment_repo: "" + steps: + - name: Checkout actions folder + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + with: + sparse-checkout: | + actions + persist-credentials: false + - name: Setup Scripts + uses: ./actions/setup + with: + destination: /opt/gh-aw/actions + - name: Check workflow file timestamps + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_WORKFLOW_FILE: "security-lint.lock.yml" + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + + agent: + needs: activation + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + model: ${{ steps.generate_aw_info.outputs.model }} + steps: + - name: Checkout actions folder + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + with: + sparse-checkout: | + actions + persist-credentials: false + - name: Setup Scripts + uses: ./actions/setup + with: + destination: /opt/gh-aw/actions + - name: Checkout repository + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + if: | + github.event.pull_request + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Validate COPILOT_GITHUB_TOKEN secret + run: /opt/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN GitHub Copilot CLI https://githubnext.github.io/gh-aw/reference/engines/#github-copilot-default + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + - name: Install GitHub Copilot CLI + run: | + # Download official Copilot CLI installer script + curl -fsSL https://raw.githubusercontent.com/github/copilot-cli/main/install.sh -o /tmp/copilot-install.sh + + # Execute the installer with the specified version + export VERSION=0.0.381 && sudo bash /tmp/copilot-install.sh + + # Cleanup + rm -f /tmp/copilot-install.sh + + # Verify installation + copilot --version + - name: Install awf binary + run: | + echo "Installing awf via installer script (requested version: v0.9.0)" + curl -sSL https://raw.githubusercontent.com/githubnext/gh-aw-firewall/main/install.sh | sudo AWF_VERSION=v0.9.0 bash + which awf + awf --version + - name: Determine automatic lockdown mode for GitHub MCP server + id: determine-automatic-lockdown + env: + TOKEN_CHECK: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + if: env.TOKEN_CHECK != '' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const determineAutomaticLockdown = require('/opt/gh-aw/actions/determine_automatic_lockdown.cjs'); + await determineAutomaticLockdown(github, context, core); + - name: Download container images + run: bash /opt/gh-aw/actions/download_docker_images.sh ghcr.io/github/github-mcp-server:v0.28.1 ghcr.io/githubnext/gh-aw-mcpg:v0.0.56 + - name: Start MCP gateway + id: start-mcp-gateway + env: + GITHUB_MCP_LOCKDOWN: ${{ steps.determine-automatic-lockdown.outputs.lockdown == 'true' && '1' || '0' }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-config + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="80" + export MCP_GATEWAY_DOMAIN="host.docker.internal" + MCP_GATEWAY_API_KEY="" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + export MCP_GATEWAY_API_KEY + + # Register API key as secret to mask it from logs + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export GH_AW_ENGINE="copilot" + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e DEBUG="*" -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_LOCKDOWN -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/githubnext/gh-aw-mcpg:v0.0.56' + + mkdir -p /home/runner/.copilot + cat << MCPCONFIG_EOF | bash /opt/gh-aw/actions/start_mcp_gateway.sh + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v0.28.1", + "env": { + "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "repos" + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}" + } + } + MCPCONFIG_EOF + - name: Generate agentic run info + id: generate_aw_info + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const fs = require('fs'); + + const awInfo = { + engine_id: "copilot", + engine_name: "GitHub Copilot CLI", + model: process.env.GH_AW_MODEL_AGENT_COPILOT || "", + version: "", + agent_version: "0.0.381", + workflow_name: "Security Lint", + experimental: false, + supports_tools_allowlist: true, + supports_http_transport: true, + run_id: context.runId, + run_number: context.runNumber, + run_attempt: process.env.GITHUB_RUN_ATTEMPT, + repository: context.repo.owner + '/' + context.repo.repo, + ref: context.ref, + sha: context.sha, + actor: context.actor, + event_name: context.eventName, + staged: false, + network_mode: "defaults", + allowed_domains: ["defaults","github.com","raw.githubusercontent.com"], + firewall_enabled: true, + awf_version: "v0.9.0", + awmg_version: "v0.0.56", + steps: { + firewall: "squid" + }, + created_at: new Date().toISOString() + }; + + // Write to /tmp/gh-aw directory to avoid inclusion in PR + const tmpPath = '/tmp/gh-aw/aw_info.json'; + fs.writeFileSync(tmpPath, JSON.stringify(awInfo, null, 2)); + console.log('Generated aw_info.json at:', tmpPath); + console.log(JSON.stringify(awInfo, null, 2)); + + // Set model as output for reuse in other steps/jobs + core.setOutput('model', awInfo.model); + - name: Generate workflow overview + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { generateWorkflowOverview } = require('/opt/gh-aw/actions/generate_workflow_overview.cjs'); + await generateWorkflowOverview(core); + - name: Create prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: | + bash /opt/gh-aw/actions/create_prompt_first.sh + cat << 'PROMPT_EOF' > "$GH_AW_PROMPT" + # Security and Code Quality Checks + + This workflow performs automated security scanning and linting on GitHub Actions workflows to catch security issues and code quality problems before they reach production. + + ## Objectives + + 1. Run zizmor security scanner to identify workflow vulnerabilities + 2. Run actionlint to validate workflow syntax and best practices + 3. Block PRs with High or Critical security findings + 4. Provide actionable feedback to contributors + + ## Tasks + + ### 1. Install Security Tools + + Install the required tools for security scanning and linting: + + - **zizmor**: Security scanner for GitHub Actions workflows + - **actionlint**: Linter for GitHub Actions workflow files + + ```bash + # Install zizmor + echo "Installing zizmor..." + curl -sSfL https://github.com/woodruffw/zizmor/releases/latest/download/zizmor-x86_64-unknown-linux-musl -o /tmp/zizmor + chmod +x /tmp/zizmor + sudo mv /tmp/zizmor /usr/local/bin/zizmor + + # Install actionlint + echo "Installing actionlint..." + bash <(curl -sSfL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) + sudo mv ./actionlint /usr/local/bin/actionlint + + # Verify installations + echo "Verifying installations..." + zizmor --version + actionlint --version + ``` + + ### 2. Run Zizmor Security Scan + + Scan all compiled workflow files for security vulnerabilities: + + ```bash + echo "Running zizmor security scan on compiled workflows..." + + # Scan all .lock.yml files and generate both human-readable and SARIF output + if zizmor --format=sarif .github/workflows/*.lock.yml > zizmor-results.sarif 2>&1; then + echo "✅ Zizmor scan completed successfully (no issues found)" + ZIZMOR_EXIT=0 + else + ZIZMOR_EXIT=$? + echo "⚠️ Zizmor found potential issues (exit code: $ZIZMOR_EXIT)" + fi + + # Show human-readable output for review + echo "" + echo "=== Zizmor Findings (Human-Readable) ===" + zizmor .github/workflows/*.lock.yml || true + + # Display SARIF summary + echo "" + echo "=== SARIF Results Summary ===" + if [ -f zizmor-results.sarif ]; then + # Count findings by severity + CRITICAL=$(jq '[.runs[].results[] | select(.level == "error")] | length' zizmor-results.sarif 2>/dev/null || echo "0") + HIGH=$(jq '[.runs[].results[] | select(.level == "warning")] | length' zizmor-results.sarif 2>/dev/null || echo "0") + MEDIUM=$(jq '[.runs[].results[] | select(.level == "note")] | length' zizmor-results.sarif 2>/dev/null || echo "0") + + echo "Critical/High: $CRITICAL" + echo "Medium: $HIGH" + echo "Low/Info: $MEDIUM" + + # Save exit code for later check + echo "$ZIZMOR_EXIT" > /tmp/zizmor-exit-code + else + echo "No SARIF file generated" + echo "0" > /tmp/zizmor-exit-code + fi + ``` + + ### 3. Run Actionlint + + Validate workflow files for syntax errors and best practices: + + ```bash + echo "Running actionlint on compiled workflows..." + + # Run actionlint with shellcheck integration + if actionlint -color .github/workflows/*.lock.yml; then + echo "✅ Actionlint validation passed" + ACTIONLINT_EXIT=0 + else + ACTIONLINT_EXIT=$? + echo "❌ Actionlint found issues (exit code: $ACTIONLINT_EXIT)" + fi + + echo "$ACTIONLINT_EXIT" > /tmp/actionlint-exit-code + ``` + + ### 4. Check for Critical Issues + + Determine if the workflow should fail based on severity of findings: + + ```bash + echo "Checking for critical security issues..." + + ZIZMOR_EXIT=$(cat /tmp/zizmor-exit-code) + ACTIONLINT_EXIT=$(cat /tmp/actionlint-exit-code) + + echo "Zizmor exit code: $ZIZMOR_EXIT" + echo "Actionlint exit code: $ACTIONLINT_EXIT" + + # Check for high/critical severity issues in zizmor SARIF output + if [ -f zizmor-results.sarif ]; then + CRITICAL_COUNT=$(jq '[.runs[].results[] | select(.level == "error")] | length' zizmor-results.sarif 2>/dev/null || echo "0") + + if [ "$CRITICAL_COUNT" -gt 0 ]; then + echo "❌ Found $CRITICAL_COUNT critical/high severity security issues!" + echo "These must be fixed before merging." + echo "" + echo "Run locally to see details:" + echo " make security-lint" + exit 1 + fi + fi + + # Fail on actionlint errors (syntax issues are always critical) + if [ "$ACTIONLINT_EXIT" -ne 0 ]; then + echo "❌ Actionlint found critical issues that must be fixed" + echo "" + echo "Run locally to see details:" + echo " make actionlint" + exit 1 + fi + + echo "✅ No critical issues found - all checks passed!" + ``` + + ## Notes + + - **Pre-commit hooks**: Consider installing pre-commit hooks locally for faster feedback + - **Local testing**: Run `make security-lint` locally before pushing + - **Documentation**: See DEVGUIDE.md for setup instructions + - **False positives**: If you believe a finding is a false positive, document it in the PR description + + ## References + + - Zizmor documentation: https://docs.zizmor.sh/ + - Actionlint repository: https://github.com/rhysd/actionlint + - Pre-commit framework: https://pre-commit.com/ + + PROMPT_EOF + - name: Append XPIA security instructions to prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: | + cat "/opt/gh-aw/prompts/xpia_prompt.md" >> "$GH_AW_PROMPT" + - name: Append temporary folder instructions to prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: | + cat "/opt/gh-aw/prompts/temp_folder_prompt.md" >> "$GH_AW_PROMPT" + - name: Append GitHub context to prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + cat << 'PROMPT_EOF' >> "$GH_AW_PROMPT" + + The following GitHub context information is available for this workflow: + {{#if __GH_AW_GITHUB_ACTOR__ }} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if __GH_AW_GITHUB_REPOSITORY__ }} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if __GH_AW_GITHUB_WORKSPACE__ }} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }} + - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }} + - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }} + - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ + {{/if}} + {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }} + - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__ + {{/if}} + {{#if __GH_AW_GITHUB_RUN_ID__ }} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + PROMPT_EOF + - name: Substitute placeholders + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }} + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + with: + script: | + const substitutePlaceholders = require('/opt/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID, + GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE + } + }); + - name: Interpolate variables and render templates + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + run: bash /opt/gh-aw/actions/print_prompt_summary.sh + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool shell(cat) + # --allow-tool shell(date) + # --allow-tool shell(echo) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(ls) + # --allow-tool shell(pwd) + # --allow-tool shell(sort) + # --allow-tool shell(tail) + # --allow-tool shell(uniq) + # --allow-tool shell(wc) + # --allow-tool shell(yq) + # --allow-tool write + timeout-minutes: 10 + run: | + set -o pipefail + sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount /tmp:/tmp:rw --mount "${GITHUB_WORKSPACE}:${GITHUB_WORKSPACE}:rw" --mount /usr/bin/date:/usr/bin/date:ro --mount /usr/bin/gh:/usr/bin/gh:ro --mount /usr/bin/yq:/usr/bin/yq:ro --mount /usr/local/bin/copilot:/usr/local/bin/copilot:ro --mount /home/runner/.copilot:/home/runner/.copilot:rw --mount /opt/gh-aw:/opt/gh-aw:ro --allow-domains api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.9.0 \ + -- /usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-tool github --allow-tool 'shell(cat)' --allow-tool 'shell(date)' --allow-tool 'shell(echo)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(ls)' --allow-tool 'shell(pwd)' --allow-tool 'shell(sort)' --allow-tool 'shell(tail)' --allow-tool 'shell(uniq)' --allow-tool 'shell(wc)' --allow-tool 'shell(yq)' --allow-tool write --allow-all-paths --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"${GH_AW_MODEL_DETECTION_COPILOT:+ --model "$GH_AW_MODEL_DETECTION_COPILOT"} \ + 2>&1 | tee /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_MODEL_DETECTION_COPILOT: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }} + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }} + GITHUB_WORKSPACE: ${{ github.workspace }} + XDG_CONFIG_HOME: /home/runner + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: | + # Copy Copilot session state files to logs folder for artifact collection + # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them + SESSION_STATE_DIR="$HOME/.copilot/session-state" + LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs" + + if [ -d "$SESSION_STATE_DIR" ]; then + echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR" + mkdir -p "$LOGS_DIR" + cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true + echo "Session state files copied successfully" + else + echo "No session-state directory found at $SESSION_STATE_DIR" + fi + - name: Stop MCP gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + run: | + bash /opt/gh-aw/actions/stop_mcp_gateway.sh ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + - name: Redact secrets in logs + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN' + SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload engine output files + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + with: + name: agent_outputs + path: | + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + if-no-files-found: ignore + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP gateway logs for step summary + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Print firewall logs + if: always() + continue-on-error: true + env: + AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs + run: awf logs summary | tee -a "$GITHUB_STEP_SUMMARY" + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + with: + name: agent-artifacts + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/sandbox/firewall/logs/ + /tmp/gh-aw/agent-stdio.log + if-no-files-found: ignore + + pre_activation: + if: (github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id) + runs-on: ubuntu-slim + permissions: + contents: read + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + steps: + - name: Checkout actions folder + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + with: + sparse-checkout: | + actions + persist-credentials: false + - name: Setup Scripts + uses: ./actions/setup + with: + destination: /opt/gh-aw/actions + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + GH_AW_REQUIRED_ROLES: admin,maintainer,write + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('/opt/gh-aw/actions/check_membership.cjs'); + await main(); + diff --git a/.github/workflows/security-lint.md b/.github/workflows/security-lint.md new file mode 100644 index 0000000000..e9063a8cec --- /dev/null +++ b/.github/workflows/security-lint.md @@ -0,0 +1,177 @@ +--- +name: Security Lint +description: Automated security scanning and workflow linting for GitHub Actions +on: + pull_request: + paths: + - '.github/workflows/**' + push: + branches: [main] +permissions: + contents: read +engine: copilot +network: + allowed: + - defaults + - github.com + - raw.githubusercontent.com +sandbox: + agent: awf +tools: + bash: + github: + toolsets: [repos] +timeout-minutes: 10 +strict: true +--- + +# Security and Code Quality Checks + +This workflow performs automated security scanning and linting on GitHub Actions workflows to catch security issues and code quality problems before they reach production. + +## Objectives + +1. Run zizmor security scanner to identify workflow vulnerabilities +2. Run actionlint to validate workflow syntax and best practices +3. Block PRs with High or Critical security findings +4. Provide actionable feedback to contributors + +## Tasks + +### 1. Install Security Tools + +Install the required tools for security scanning and linting: + +- **zizmor**: Security scanner for GitHub Actions workflows +- **actionlint**: Linter for GitHub Actions workflow files + +```bash +# Install zizmor +echo "Installing zizmor..." +curl -sSfL https://github.com/woodruffw/zizmor/releases/latest/download/zizmor-x86_64-unknown-linux-musl -o /tmp/zizmor +chmod +x /tmp/zizmor +sudo mv /tmp/zizmor /usr/local/bin/zizmor + +# Install actionlint +echo "Installing actionlint..." +bash <(curl -sSfL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) +sudo mv ./actionlint /usr/local/bin/actionlint + +# Verify installations +echo "Verifying installations..." +zizmor --version +actionlint --version +``` + +### 2. Run Zizmor Security Scan + +Scan all compiled workflow files for security vulnerabilities: + +```bash +echo "Running zizmor security scan on compiled workflows..." + +# Scan all .lock.yml files and generate both human-readable and SARIF output +if zizmor --format=sarif .github/workflows/*.lock.yml > zizmor-results.sarif 2>&1; then + echo "✅ Zizmor scan completed successfully (no issues found)" + ZIZMOR_EXIT=0 +else + ZIZMOR_EXIT=$? + echo "⚠️ Zizmor found potential issues (exit code: $ZIZMOR_EXIT)" +fi + +# Show human-readable output for review +echo "" +echo "=== Zizmor Findings (Human-Readable) ===" +zizmor .github/workflows/*.lock.yml || true + +# Display SARIF summary +echo "" +echo "=== SARIF Results Summary ===" +if [ -f zizmor-results.sarif ]; then + # Count findings by severity + CRITICAL=$(jq '[.runs[].results[] | select(.level == "error")] | length' zizmor-results.sarif 2>/dev/null || echo "0") + HIGH=$(jq '[.runs[].results[] | select(.level == "warning")] | length' zizmor-results.sarif 2>/dev/null || echo "0") + MEDIUM=$(jq '[.runs[].results[] | select(.level == "note")] | length' zizmor-results.sarif 2>/dev/null || echo "0") + + echo "Critical/High: $CRITICAL" + echo "Medium: $HIGH" + echo "Low/Info: $MEDIUM" + + # Save exit code for later check + echo "$ZIZMOR_EXIT" > /tmp/zizmor-exit-code +else + echo "No SARIF file generated" + echo "0" > /tmp/zizmor-exit-code +fi +``` + +### 3. Run Actionlint + +Validate workflow files for syntax errors and best practices: + +```bash +echo "Running actionlint on compiled workflows..." + +# Run actionlint with shellcheck integration +if actionlint -color .github/workflows/*.lock.yml; then + echo "✅ Actionlint validation passed" + ACTIONLINT_EXIT=0 +else + ACTIONLINT_EXIT=$? + echo "❌ Actionlint found issues (exit code: $ACTIONLINT_EXIT)" +fi + +echo "$ACTIONLINT_EXIT" > /tmp/actionlint-exit-code +``` + +### 4. Check for Critical Issues + +Determine if the workflow should fail based on severity of findings: + +```bash +echo "Checking for critical security issues..." + +ZIZMOR_EXIT=$(cat /tmp/zizmor-exit-code) +ACTIONLINT_EXIT=$(cat /tmp/actionlint-exit-code) + +echo "Zizmor exit code: $ZIZMOR_EXIT" +echo "Actionlint exit code: $ACTIONLINT_EXIT" + +# Check for high/critical severity issues in zizmor SARIF output +if [ -f zizmor-results.sarif ]; then + CRITICAL_COUNT=$(jq '[.runs[].results[] | select(.level == "error")] | length' zizmor-results.sarif 2>/dev/null || echo "0") + + if [ "$CRITICAL_COUNT" -gt 0 ]; then + echo "❌ Found $CRITICAL_COUNT critical/high severity security issues!" + echo "These must be fixed before merging." + echo "" + echo "Run locally to see details:" + echo " make security-lint" + exit 1 + fi +fi + +# Fail on actionlint errors (syntax issues are always critical) +if [ "$ACTIONLINT_EXIT" -ne 0 ]; then + echo "❌ Actionlint found critical issues that must be fixed" + echo "" + echo "Run locally to see details:" + echo " make actionlint" + exit 1 +fi + +echo "✅ No critical issues found - all checks passed!" +``` + +## Notes + +- **Pre-commit hooks**: Consider installing pre-commit hooks locally for faster feedback +- **Local testing**: Run `make security-lint` locally before pushing +- **Documentation**: See DEVGUIDE.md for setup instructions +- **False positives**: If you believe a finding is a false positive, document it in the PR description + +## References + +- Zizmor documentation: https://docs.zizmor.sh/ +- Actionlint repository: https://github.com/rhysd/actionlint +- Pre-commit framework: https://pre-commit.com/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..f5c1b28027 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,34 @@ +# Pre-commit hooks for gh-aw +# Install pre-commit: pip install pre-commit +# Setup hooks: pre-commit install +# Run manually: pre-commit run --all-files + +repos: + - repo: local + hooks: + # Security scanning with zizmor + - id: zizmor + name: zizmor security scan + entry: zizmor + language: system + files: \.github/workflows/.*\.(lock\.yml|md)$ + pass_filenames: true + description: Scan GitHub Actions workflows for security vulnerabilities + + # Workflow linting with actionlint + - id: actionlint + name: actionlint workflow linting + entry: actionlint + language: system + files: \.github/workflows/.*\.lock\.yml$ + pass_filenames: true + description: Lint GitHub Actions workflow files for best practices and errors + + # Shell script validation with shellcheck + - id: shellcheck + name: shellcheck shell script validation + entry: shellcheck + language: system + files: \.(sh|bash)$ + types: [file, shell] + description: Validate shell scripts for common issues and best practices diff --git a/DEVGUIDE.md b/DEVGUIDE.md index c83d75f5fc..8d3282b1d8 100644 --- a/DEVGUIDE.md +++ b/DEVGUIDE.md @@ -143,6 +143,52 @@ make security-scan # Run gosec, govulncheck, and trivy ``` **When to use**: Before releases or when checking for vulnerabilities. +#### Run security linting on workflows +```bash +make security-lint # Run zizmor and actionlint on workflows +``` +**What it does**: Scans GitHub Actions workflow files for security vulnerabilities and best practices violations using zizmor and actionlint. + +**When to use**: +- Before committing workflow changes +- When reviewing workflow security +- As part of pre-commit hooks + +**Setup (optional but recommended)**: +```bash +# Install pre-commit framework +pip install pre-commit + +# Install pre-commit hooks +pre-commit install + +# Run hooks manually on all files +pre-commit run --all-files +``` + +**Required tools**: +- **zizmor**: Security scanner for GitHub Actions + ```bash + # Install on Linux + curl -sSfL https://github.com/woodruffw/zizmor/releases/latest/download/zizmor-x86_64-unknown-linux-musl -o /usr/local/bin/zizmor + chmod +x /usr/local/bin/zizmor + + # Install on macOS + brew install zizmor + ``` + +- **actionlint**: Workflow linter (optional - gh-aw provides fallback) + ```bash + # Install on Linux/macOS + bash <(curl -sSfL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) + sudo mv ./actionlint /usr/local/bin/actionlint + + # Or with Homebrew on macOS + brew install actionlint + ``` + +**Note**: If tools aren't installed, `make security-lint` will show installation instructions and use fallbacks where possible. + #### Run performance benchmarks ```bash make bench # Run all benchmarks (~30s) diff --git a/Makefile b/Makefile index 472b73b5b9..22e3350eba 100644 --- a/Makefile +++ b/Makefile @@ -425,6 +425,32 @@ actionlint: build @echo "Validating workflows with actionlint..." ./$(BINARY_NAME) compile --actionlint +# Run security linting on workflows (zizmor + actionlint) +.PHONY: security-lint +security-lint: build recompile ## Run security linting on workflows + @echo "Running security linting on workflows..." + @echo "" + @echo "=== Running Zizmor Security Scan ===" + @if command -v zizmor >/dev/null 2>&1; then \ + zizmor .github/workflows/*.lock.yml; \ + else \ + echo "⚠️ Zizmor not installed. Install with:"; \ + echo " curl -sSfL https://github.com/woodruffw/zizmor/releases/latest/download/zizmor-x86_64-unknown-linux-musl -o /usr/local/bin/zizmor"; \ + echo " chmod +x /usr/local/bin/zizmor"; \ + echo ""; \ + echo "Skipping zizmor scan..."; \ + fi + @echo "" + @echo "=== Running Actionlint ===" + @if command -v actionlint >/dev/null 2>&1; then \ + actionlint .github/workflows/*.lock.yml; \ + else \ + echo "⚠️ Actionlint not installed. Using gh-aw compile --actionlint instead..."; \ + ./$(BINARY_NAME) compile --actionlint; \ + fi + @echo "" + @echo "✓ Security linting complete" + # Format code .PHONY: fmt fmt: fmt-go fmt-cjs fmt-json @@ -718,6 +744,7 @@ help: @echo " security-gosec - Run gosec Go security scanner" @echo " security-govulncheck - Run govulncheck for known vulnerabilities" @echo " security-trivy - Run trivy filesystem scanner" + @echo " security-lint - Run security linting on workflows (zizmor + actionlint)" @echo " actionlint - Validate workflows with actionlint (depends on build)" @echo " validate-workflows - Validate compiled workflow lock files (depends on build)" @echo " install - Install binary locally" diff --git a/specs/artifacts.md b/specs/artifacts.md index df35b5d640..be8d4b7715 100644 --- a/specs/artifacts.md +++ b/specs/artifacts.md @@ -22,13 +22,13 @@ This section provides an overview of artifacts organized by job name, with dupli - `agent-artifacts` - **Paths**: `/tmp/gh-aw/agent-stdio.log`, `/tmp/gh-aw/aw-prompts/prompt.txt`, `/tmp/gh-aw/aw.patch`, `/tmp/gh-aw/aw_info.json`, `/tmp/gh-aw/mcp-logs/`, `/tmp/gh-aw/safe-inputs/logs/`, `/tmp/gh-aw/sandbox/firewall/logs/` - - **Used in**: 67 workflow(s) - agent-performance-analyzer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, campaign-generator.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-repo-chronicle.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dev.md, dictation-prompt.md, example-custom-error-patterns.md, example-permissions-warning.md, firewall.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, metrics-collector.md, notion-issue-summary.md, pdf-summary.md, plan.md, playground-assign-to-agent.md, playground-org-project-update-issue.md, playground-snapshots-refresh.md, poem-bot.md, pr-nitpick-reviewer.md, python-data-charts.md, q.md, release.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md + - **Used in**: 68 workflow(s) - agent-performance-analyzer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, campaign-generator.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-repo-chronicle.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dev.md, dictation-prompt.md, example-custom-error-patterns.md, example-permissions-warning.md, firewall.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, metrics-collector.md, notion-issue-summary.md, pdf-summary.md, plan.md, playground-assign-to-agent.md, playground-org-project-update-issue.md, playground-snapshots-refresh.md, poem-bot.md, pr-nitpick-reviewer.md, python-data-charts.md, q.md, release.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, security-lint.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md - `agent-output` - **Paths**: `${{ env.GH_AW_AGENT_OUTPUT }}` - **Used in**: 63 workflow(s) - agent-performance-analyzer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, campaign-generator.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, cloclo.md, code-scanning-fixer.md, commit-changes-analyzer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-choice-test.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-repo-chronicle.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dev.md, dictation-prompt.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, go-pattern-detector.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-classifier.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, notion-issue-summary.md, pdf-summary.md, plan.md, playground-assign-to-agent.md, playground-org-project-update-issue.md, playground-snapshots-refresh.md, poem-bot.md, pr-nitpick-reviewer.md, python-data-charts.md, q.md, release.md, repository-quality-improver.md, research.md, scout.md, security-compliance.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, tidy.md, typist.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md - `agent_outputs` - **Paths**: `/tmp/gh-aw/mcp-config/logs/`, `/tmp/gh-aw/redacted-urls.log`, `/tmp/gh-aw/sandbox/agent/logs/` - - **Used in**: 57 workflow(s) - agent-performance-analyzer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, code-scanning-fixer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-repo-chronicle.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dev.md, dictation-prompt.md, example-custom-error-patterns.md, example-permissions-warning.md, firewall.md, glossary-maintainer.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, metrics-collector.md, notion-issue-summary.md, pdf-summary.md, plan.md, playground-assign-to-agent.md, playground-org-project-update-issue.md, playground-snapshots-refresh.md, poem-bot.md, pr-nitpick-reviewer.md, python-data-charts.md, q.md, release.md, repository-quality-improver.md, research.md, security-compliance.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, tidy.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md + - **Used in**: 58 workflow(s) - agent-performance-analyzer.md, ai-moderator.md, archie.md, brave.md, breaking-change-checker.md, changeset.md, ci-coach.md, ci-doctor.md, cli-consistency-checker.md, code-scanning-fixer.md, copilot-pr-merged-report.md, copilot-pr-nlp-analysis.md, craft.md, daily-copilot-token-report.md, daily-fact.md, daily-file-diet.md, daily-issues-report.md, daily-news.md, daily-repo-chronicle.md, deep-report.md, dependabot-go-checker.md, dev-hawk.md, dev.md, dictation-prompt.md, example-custom-error-patterns.md, example-permissions-warning.md, firewall.md, glossary-maintainer.md, grumpy-reviewer.md, hourly-ci-cleaner.md, issue-triage-agent.md, layout-spec-maintainer.md, mergefest.md, metrics-collector.md, notion-issue-summary.md, pdf-summary.md, plan.md, playground-assign-to-agent.md, playground-org-project-update-issue.md, playground-snapshots-refresh.md, poem-bot.md, pr-nitpick-reviewer.md, python-data-charts.md, q.md, release.md, repository-quality-improver.md, research.md, security-compliance.md, security-lint.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, tidy.md, video-analyzer.md, weekly-issue-summary.md, workflow-generator.md, workflow-health-manager.md - `cache-memory` - **Paths**: `/tmp/gh-aw/cache-memory` - **Used in**: 25 workflow(s) - ci-coach.md, ci-doctor.md, cloclo.md, code-scanning-fixer.md, copilot-pr-nlp-analysis.md, daily-copilot-token-report.md, daily-issues-report.md, daily-news.md, daily-repo-chronicle.md, deep-report.md, github-mcp-structural-analysis.md, glossary-maintainer.md, go-fan.md, grumpy-reviewer.md, pdf-summary.md, poem-bot.md, pr-nitpick-reviewer.md, python-data-charts.md, q.md, scout.md, slide-deck-maintainer.md, stale-repo-identifier.md, super-linter.md, technical-doc-writer.md, weekly-issue-summary.md @@ -4041,6 +4041,25 @@ This section provides an overview of artifacts organized by job name, with dupli - **Download path**: `/tmp/gh-aw/safeoutputs/` - **Depends on jobs**: [agent detection] +### security-lint.md + +#### Job: `agent` + +**Uploads:** + +- **Artifact**: `agent_outputs` + - **Upload paths**: + - `/tmp/gh-aw/sandbox/agent/logs/` + - `/tmp/gh-aw/redacted-urls.log` + +- **Artifact**: `agent-artifacts` + - **Upload paths**: + - `/tmp/gh-aw/aw-prompts/prompt.txt` + - `/tmp/gh-aw/aw_info.json` + - `/tmp/gh-aw/mcp-logs/` + - `/tmp/gh-aw/sandbox/firewall/logs/` + - `/tmp/gh-aw/agent-stdio.log` + ### slide-deck-maintainer.md #### Job: `agent`