diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index 8e72366766..248f97ce34 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -19,7 +19,11 @@ # gh aw compile # For more information: https://github.com/githubnext/gh-aw/blob/main/.github/aw/github-agentic-workflows.md # -# Read an issue and post a poem about it +# Find security issues in Go source code using CodeQL +# +# Resolved workflow manifest: +# Imports: +# - shared/mcp/codeql.md name: "Dev" "on": @@ -33,6 +37,7 @@ name: "Dev" permissions: contents: read issues: read + security-events: read concurrency: group: "gh-aw-${{ github.workflow }}" @@ -75,6 +80,7 @@ jobs: permissions: contents: read issues: read + security-events: read concurrency: group: "gh-aw-copilot-${{ github.workflow }}" env: @@ -108,6 +114,26 @@ jobs: persist-credentials: false - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh + - name: Install CodeQL CLI + run: "set -e\necho \"Installing CodeQL CLI...\"\n\n# Download and install CodeQL CLI\nCODEQL_VERSION=\"v2.19.3\"\nCODEQL_URL=\"https://github.com/github/codeql-cli-binaries/releases/download/${CODEQL_VERSION}/codeql-linux64.zip\"\n\n# Download CodeQL\ncurl -L -o /tmp/codeql.zip \"${CODEQL_URL}\"\n\n# Extract to a known location\nsudo unzip -q /tmp/codeql.zip -d /usr/local/\n\n# Add to PATH\necho \"/usr/local/codeql\" >> $GITHUB_PATH\n\n# Verify installation\n/usr/local/codeql/codeql --version\n\necho \"CodeQL CLI installed successfully\"\n" + - id: cache-codeql-db + name: Restore CodeQL database from cache + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + key: codeql-db-${{ github.repository }}-${{ github.sha }} + path: /tmp/codeql-db + restore-keys: | + codeql-db-${{ github.repository }}- + - if: steps.cache-codeql-db.outputs.cache-hit != 'true' + name: Create CodeQL database + run: "set -e\necho \"Creating CodeQL database...\"\n\n# Detect primary language from repository\n# Default to 'go' if detection fails\nLANGUAGE=\"go\"\n\n# Try to detect language from common files\nif [ -f \"go.mod\" ]; then\n LANGUAGE=\"go\"\nelif [ -f \"package.json\" ]; then\n LANGUAGE=\"javascript\"\nelif [ -f \"requirements.txt\" ] || [ -f \"setup.py\" ]; then\n LANGUAGE=\"python\"\nelif [ -f \"pom.xml\" ] || [ -f \"build.gradle\" ]; then\n LANGUAGE=\"java\"\nelif [ -f \"Gemfile\" ]; then\n LANGUAGE=\"ruby\"\nelif [ -f \"*.csproj\" ]; then\n LANGUAGE=\"csharp\"\nfi\n\necho \"Detected language: $LANGUAGE\"\n\n# Create database for the repository\ncodeql database create /tmp/codeql-db \\\n --language=$LANGUAGE \\\n --source-root=${{ github.workspace }} \\\n --overwrite\n\necho \"CodeQL database created successfully at /tmp/codeql-db\"\n" + - name: Install Python dependencies for CodeQL MCP server + run: "set -e\necho \"Installing Python dependencies for CodeQL MCP server...\"\n\n# Install required Python packages\npip install fastmcp httpx\n\necho \"Python dependencies installed successfully\"\n" + - name: Clone CodeQL MCP server + run: "set -e\necho \"Cloning CodeQL MCP server repository...\"\n\n# Clone the MCP server repository\ngit clone https://github.com/JordyZomer/codeql-mcp.git /tmp/codeql-mcp\n\necho \"CodeQL MCP server cloned successfully\"\n" + - name: Start CodeQL MCP server + run: "set -e\n\n# Start the CodeQL MCP server in the background\ncd /tmp/codeql-mcp\npython3 server.py &\nMCP_PID=$!\n\n# Robust health check with TCP connection test\necho \"Waiting for CodeQL MCP server to start (PID: $MCP_PID)...\"\nfor i in {1..30}; do\n # Check if process is still running\n if ! kill -0 $MCP_PID 2>/dev/null; then\n echo \"Error: CodeQL MCP server process died unexpectedly\"\n exit 1\n fi\n \n # Try to connect to the server port\n if timeout 1 bash -c \"echo > /dev/tcp/localhost/8000\" 2>/dev/null; then\n echo \"CodeQL MCP server is accepting connections on port 8000\"\n echo \"CodeQL MCP server started successfully with PID $MCP_PID\"\n exit 0\n fi\n \n echo \"Waiting for server to accept connections... (attempt $i/30)\"\n sleep 2\ndone\n\necho \"Error: CodeQL MCP server failed to accept connections after 60 seconds\"\nexit 1" + - name: Configure Git credentials env: REPO_NAME: ${{ github.repository }} @@ -168,10 +194,50 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > /opt/gh-aw/safeoutputs/config.json << 'EOF' - {"add_comment":{"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} + {"add_comment":{"max":1},"create_issue":{"max":1},"missing_data":{},"missing_tool":{},"noop":{"max":1}} EOF cat > /opt/gh-aw/safeoutputs/tools.json << 'EOF' [ + { + "description": "Create a new GitHub issue for tracking bugs, feature requests, or tasks. Use this for actionable work items that need assignment, labeling, and status tracking. For reports, announcements, or status updates that don't require task tracking, use create_discussion instead. CONSTRAINTS: Maximum 1 issue(s) can be created. Title will be prefixed with \"[security] \". Labels [security codeql] will be automatically added.", + "inputSchema": { + "additionalProperties": false, + "properties": { + "body": { + "description": "Detailed issue description in Markdown. Do NOT repeat the title as a heading since it already appears as the issue's h1. Include context, reproduction steps, or acceptance criteria as appropriate.", + "type": "string" + }, + "labels": { + "description": "Labels to categorize the issue (e.g., 'bug', 'enhancement'). Labels must exist in the repository.", + "items": { + "type": "string" + }, + "type": "array" + }, + "parent": { + "description": "Parent issue number for creating sub-issues. This is the numeric ID from the GitHub URL (e.g., 42 in github.com/owner/repo/issues/42). Can also be a temporary_id (e.g., 'aw_abc123def456') from a previously created issue in the same workflow run.", + "type": [ + "number", + "string" + ] + }, + "temporary_id": { + "description": "Unique temporary identifier for referencing this issue before it's created. Format: 'aw_' followed by 12 hex characters (e.g., 'aw_abc123def456'). Use '#aw_ID' in body text to reference other issues by their temporary_id; these are replaced with actual issue numbers after creation.", + "type": "string" + }, + "title": { + "description": "Concise issue title summarizing the bug, feature, or task. The title appears as the main heading, so keep it brief and descriptive.", + "type": "string" + } + }, + "required": [ + "title", + "body" + ], + "type": "object" + }, + "name": "create_issue" + }, { "description": "Add a comment to an existing GitHub issue, pull request, or discussion. Use this to provide feedback, answer questions, or add information to an existing conversation. For creating new items, use create_issue, create_discussion, or create_pull_request instead. CONSTRAINTS: Maximum 1 comment(s) can be added.", "inputSchema": { @@ -283,6 +349,39 @@ jobs: } } }, + "create_issue": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "parent": { + "issueOrPRNumber": true + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "temporary_id": { + "type": "string" + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, "missing_tool": { "defaultMax": 20, "fields": { @@ -373,21 +472,64 @@ jobs: env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }} + GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER: ${{ github.event.inputs.issue_number }} run: | bash /opt/gh-aw/actions/create_prompt_first.sh cat << 'PROMPT_EOF' > "$GH_AW_PROMPT" - # Read Issue and Post Poem - Read a single issue and post a poem about it as a comment in staged mode. + + # CodeQL Security Analysis for Go Code + + Analyze the Go source code in this repository to find security vulnerabilities using CodeQL. **Requirements:** - 1. Read the issue specified by the `issue_number` input - 2. Understand the issue's title, body, and context - 3. Write a creative poem inspired by the issue content - 4. Post the poem as a comment on the issue using `create_issue_comment` in staged mode - 5. The poem should be relevant, creative, and engaging + 1. Use the CodeQL MCP server to analyze the Go codebase + 2. Register the CodeQL database at `/tmp/codeql-db` with the MCP server using `register_database` + 3. Run security-focused CodeQL queries to identify potential vulnerabilities in the Go code + 4. Focus on common security issues like: + - SQL injection vulnerabilities + - Command injection risks + - Path traversal vulnerabilities + - Insecure cryptographic practices + - Uncontrolled resource consumption + - Unsafe reflection usage + 5. Decode the query results using `decode_bqrs` to get human-readable output + 6. Analyze the findings and create a summary report + 7. If security issues are found, create a new issue with: + - Clear description of each vulnerability + - Location (file and line numbers) + - Severity assessment + - Recommended fixes + 8. Post a comment on issue #__GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER__ with a summary of the analysis + 9. Use staged mode to preview all outputs before creating them + + **CodeQL Database Location**: `/tmp/codeql-db` + + **Expected Workflow**: + 1. Register the database: `register_database("/tmp/codeql-db")` + 2. Run security queries or evaluate specific security patterns + 3. Decode results to JSON format for analysis + 4. Generate actionable security report + 5. Create issue if vulnerabilities found + 6. Comment on the triggering issue with summary 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_EVENT_INPUTS_ISSUE_NUMBER: ${{ github.event.inputs.issue_number }} + 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_EVENT_INPUTS_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER + } + }); - name: Append temporary folder instructions to prompt env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt @@ -406,7 +548,7 @@ jobs: To create or modify GitHub resources (issues, discussions, pull requests, etc.), you MUST call the appropriate safe output tool. Simply writing content will NOT work - the workflow requires actual tool calls. - **Available tools**: add_comment, missing_tool, noop + **Available tools**: add_comment, create_issue, missing_tool, noop **Critical**: Tool calls write structured data that downstream jobs process. Without tool calls, follow-up actions will be skipped. @@ -488,6 +630,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_GITHUB_EVENT_INPUTS_ISSUE_NUMBER: ${{ github.event.inputs.issue_number }} with: script: | const { setupGlobals } = require('/opt/gh-aw/actions/setup_globals.cjs'); @@ -501,9 +644,11 @@ jobs: - name: Execute GitHub Copilot CLI id: agentic_execution # Copilot CLI tool arguments (sorted): + # --allow-tool codeql + # --allow-tool codeql(*) # --allow-tool github # --allow-tool safeoutputs - timeout-minutes: 5 + timeout-minutes: 15 run: | set -o pipefail COPILOT_CLI_INSTRUCTION="$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" @@ -511,7 +656,7 @@ jobs: mkdir -p /tmp/gh-aw/ mkdir -p /tmp/gh-aw/agent/ mkdir -p /tmp/gh-aw/sandbox/agent/logs/ - copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool github --allow-tool safeoutputs --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"} 2>&1 | tee /tmp/gh-aw/agent-stdio.log + copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --allow-tool codeql --allow-tool 'codeql(*)' --allow-tool github --allow-tool safeoutputs --share /tmp/gh-aw/sandbox/agent/logs/conversation.md --prompt "$COPILOT_CLI_INSTRUCTION"${GH_AW_MODEL_AGENT_COPILOT:+ --model "$GH_AW_MODEL_AGENT_COPILOT"} 2>&1 | tee /tmp/gh-aw/agent-stdio.log env: COPILOT_AGENT_RUNNER_TYPE: STANDALONE COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} @@ -770,7 +915,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: WORKFLOW_NAME: "Dev" - WORKFLOW_DESCRIPTION: "Read an issue and post a poem about it" + WORKFLOW_DESCRIPTION: "Find security issues in Go source code using CodeQL" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | @@ -935,7 +1080,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"missing_data\":{},\"missing_tool\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_issue\":{\"labels\":[\"security\",\"codeql\"],\"max\":1,\"title_prefix\":\"[security] \"},\"missing_data\":{},\"missing_tool\":{}}" GH_AW_SAFE_OUTPUTS_STAGED: "true" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/dev.md b/.github/workflows/dev.md index 1b04203252..b9bc5ed32f 100644 --- a/.github/workflows/dev.md +++ b/.github/workflows/dev.md @@ -7,8 +7,8 @@ on: required: true type: string name: Dev -description: Read an issue and post a poem about it -timeout-minutes: 5 +description: Find security issues in Go source code using CodeQL +timeout-minutes: 15 strict: false sandbox: false engine: copilot @@ -16,6 +16,7 @@ engine: copilot permissions: contents: read issues: read + security-events: read network: allowed: @@ -25,19 +26,49 @@ tools: github: toolsets: [issues] +imports: + - shared/mcp/codeql.md + safe-outputs: staged: true add-comment: max: 1 + create-issue: + title-prefix: "[security] " + labels: [security, codeql] --- -# Read Issue and Post Poem +# CodeQL Security Analysis for Go Code -Read a single issue and post a poem about it as a comment in staged mode. +Analyze the Go source code in this repository to find security vulnerabilities using CodeQL. **Requirements:** -1. Read the issue specified by the `issue_number` input -2. Understand the issue's title, body, and context -3. Write a creative poem inspired by the issue content -4. Post the poem as a comment on the issue using `create_issue_comment` in staged mode -5. The poem should be relevant, creative, and engaging +1. Use the CodeQL MCP server to analyze the Go codebase +2. Register the CodeQL database at `/tmp/codeql-db` with the MCP server using `register_database` +3. Run security-focused CodeQL queries to identify potential vulnerabilities in the Go code +4. Focus on common security issues like: + - SQL injection vulnerabilities + - Command injection risks + - Path traversal vulnerabilities + - Insecure cryptographic practices + - Uncontrolled resource consumption + - Unsafe reflection usage +5. Decode the query results using `decode_bqrs` to get human-readable output +6. Analyze the findings and create a summary report +7. If security issues are found, create a new issue with: + - Clear description of each vulnerability + - Location (file and line numbers) + - Severity assessment + - Recommended fixes +8. Post a comment on issue #${{ github.event.inputs.issue_number }} with a summary of the analysis +9. Use staged mode to preview all outputs before creating them + +**CodeQL Database Location**: `/tmp/codeql-db` + +**Expected Workflow**: +1. Register the database: `register_database("/tmp/codeql-db")` +2. Run security queries or evaluate specific security patterns +3. Decode results to JSON format for analysis +4. Generate actionable security report +5. Create issue if vulnerabilities found +6. Comment on the triggering issue with summary diff --git a/.github/workflows/shared/mcp/codeql.md b/.github/workflows/shared/mcp/codeql.md new file mode 100644 index 0000000000..0075c0deb8 --- /dev/null +++ b/.github/workflows/shared/mcp/codeql.md @@ -0,0 +1,271 @@ +--- +mcp-servers: + codeql: + type: http + url: http://localhost:8000 + allowed: ["*"] + +steps: + - name: Install CodeQL CLI + run: | + set -e + echo "Installing CodeQL CLI..." + + # Download and install CodeQL CLI + CODEQL_VERSION="v2.19.3" + CODEQL_URL="https://github.com/github/codeql-cli-binaries/releases/download/${CODEQL_VERSION}/codeql-linux64.zip" + + # Download CodeQL + curl -L -o /tmp/codeql.zip "${CODEQL_URL}" + + # Extract to a known location + sudo unzip -q /tmp/codeql.zip -d /usr/local/ + + # Add to PATH + echo "/usr/local/codeql" >> $GITHUB_PATH + + # Verify installation + /usr/local/codeql/codeql --version + + echo "CodeQL CLI installed successfully" + + - name: Restore CodeQL database from cache + id: cache-codeql-db + uses: actions/cache@v4 + with: + path: /tmp/codeql-db + key: codeql-db-${{ github.repository }}-${{ github.sha }} + restore-keys: | + codeql-db-${{ github.repository }}- + + - name: Create CodeQL database + if: steps.cache-codeql-db.outputs.cache-hit != 'true' + run: | + set -e + echo "Creating CodeQL database..." + + # Detect primary language from repository + # Default to 'go' if detection fails + LANGUAGE="go" + + # Try to detect language from common files + if [ -f "go.mod" ]; then + LANGUAGE="go" + elif [ -f "package.json" ]; then + LANGUAGE="javascript" + elif [ -f "requirements.txt" ] || [ -f "setup.py" ]; then + LANGUAGE="python" + elif [ -f "pom.xml" ] || [ -f "build.gradle" ]; then + LANGUAGE="java" + elif [ -f "Gemfile" ]; then + LANGUAGE="ruby" + elif [ -f "*.csproj" ]; then + LANGUAGE="csharp" + fi + + echo "Detected language: $LANGUAGE" + + # Create database for the repository + codeql database create /tmp/codeql-db \ + --language=$LANGUAGE \ + --source-root=${{ github.workspace }} \ + --overwrite + + echo "CodeQL database created successfully at /tmp/codeql-db" + + - name: Install Python dependencies for CodeQL MCP server + run: | + set -e + echo "Installing Python dependencies for CodeQL MCP server..." + + # Install required Python packages + pip install fastmcp httpx + + echo "Python dependencies installed successfully" + + - name: Clone CodeQL MCP server + run: | + set -e + echo "Cloning CodeQL MCP server repository..." + + # Clone the MCP server repository + git clone https://github.com/JordyZomer/codeql-mcp.git /tmp/codeql-mcp + + echo "CodeQL MCP server cloned successfully" + + - name: Start CodeQL MCP server + run: | + set -e + + # Start the CodeQL MCP server in the background + cd /tmp/codeql-mcp + python3 server.py & + MCP_PID=$! + + # Robust health check with TCP connection test + echo "Waiting for CodeQL MCP server to start (PID: $MCP_PID)..." + for i in {1..30}; do + # Check if process is still running + if ! kill -0 $MCP_PID 2>/dev/null; then + echo "Error: CodeQL MCP server process died unexpectedly" + exit 1 + fi + + # Try to connect to the server port + if timeout 1 bash -c "echo > /dev/tcp/localhost/8000" 2>/dev/null; then + echo "CodeQL MCP server is accepting connections on port 8000" + echo "CodeQL MCP server started successfully with PID $MCP_PID" + exit 0 + fi + + echo "Waiting for server to accept connections... (attempt $i/30)" + sleep 2 + done + + echo "Error: CodeQL MCP server failed to accept connections after 60 seconds" + exit 1 +--- + +