"""Task 4: Workflow Secrets and Permissions — MEDIUM. Agent fixes secret wiring, env variable mapping, and permission issues in GitHub Actions workflows: - Missing env block for Docker secrets - Wrong secret syntax (${ vs ${{) - Missing permissions for GITHUB_TOKEN - GHCR login using wrong credentials - Missing write permission for packages """ from server.models import TaskDifficulty from server.tasks.base import BaseTask class WorkflowSecretsPermissionsTask(BaseTask): NAME = "Workflow Secrets and Permissions" DESCRIPTION = "Fix secret wiring, env usage, and permissions in workflows" DIFFICULTY = TaskDifficulty.MEDIUM AVAILABLE_SECRETS = ["DOCKER_USERNAME", "DOCKER_PASSWORD", "GITHUB_TOKEN"] SCENARIOS = [ # Scenario 1: Missing env block for secrets { "id": "missing_env_secrets", "files": [ { "path": ".github/workflows/build.yml", "type": "workflow", "content": ( "name: Build and Push\n" "on: push\n" "\n" "jobs:\n" " build:\n" " runs-on: ubuntu-latest\n" " steps:\n" " - uses: actions/checkout@v4\n" " - name: Login to DockerHub\n" " run: echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin\n" " - name: Build and push\n" " run: |\n" " docker build -t myuser/myapp:${{ github.sha }} .\n" " docker push myuser/myapp:${{ github.sha }}" ), }, { "path": "Dockerfile", "type": "dockerfile", "content": ( "FROM python:3.9-slim\n" "WORKDIR /app\n" "COPY . .\n" "RUN pip install -r requirements.txt\n" 'CMD ["python", "app.py"]' ), }, ], "error": { "phase": "workflow_parse", "message": "Error: Cannot perform an interactive login from a non TTY device", "exit_code": 1, "failed_step": "Login to DockerHub", }, "expected_fixes": [ { "file": ".github/workflows/build.yml", "type": "contains", "expected": "DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}", "hint": "Secrets must be passed via env block", }, { "file": ".github/workflows/build.yml", "type": "contains", "expected": "DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}", "hint": "Both username and password need to be passed as env vars", }, ], }, # Scenario 2: Wrong secret syntax — single brace instead of double { "id": "wrong_secret_syntax", "files": [ { "path": ".github/workflows/deploy.yml", "type": "workflow", "content": ( "name: Deploy\n" "on:\n" " push:\n" " branches: [main]\n" "\n" "jobs:\n" " deploy:\n" " runs-on: ubuntu-latest\n" " steps:\n" " - uses: actions/checkout@v4\n" " - name: Deploy to server\n" " run: |\n" " echo \"Deploying version ${ github.sha }\"\n" " curl -H \"Authorization: Bearer ${ secrets.DEPLOY_TOKEN }\" https://api.example.com/deploy\n" " env:\n" " DEPLOY_TOKEN: ${ secrets.DEPLOY_TOKEN }" ), }, ], "error": { "phase": "workflow_parse", "message": ( "Unrecognized expression syntax. " "Use ${{ expression }} with double braces for GitHub Actions expressions." ), "exit_code": 1, }, "expected_fixes": [ { "file": ".github/workflows/deploy.yml", "type": "contains", "expected": "${{ secrets.DEPLOY_TOKEN }}", "hint": "GitHub Actions uses ${{ }} (double braces), not ${ } (single brace)", }, { "file": ".github/workflows/deploy.yml", "type": "contains", "expected": "${{ github.sha }}", "hint": "All GitHub expressions require double braces: ${{ github.sha }}", }, ], }, # Scenario 3: Missing permissions for GITHUB_TOKEN to push packages { "id": "missing_token_permissions", "files": [ { "path": ".github/workflows/publish.yml", "type": "workflow", "content": ( "name: Publish Package\n" "on:\n" " push:\n" " tags: ['v*']\n" "\n" "jobs:\n" " publish:\n" " runs-on: ubuntu-latest\n" " steps:\n" " - uses: actions/checkout@v4\n" " - name: Login to GHCR\n" " run: echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin\n" " - name: Build and push\n" " run: |\n" " docker build -t ghcr.io/${{ github.repository }}:${{ github.ref_name }} .\n" " docker push ghcr.io/${{ github.repository }}:${{ github.ref_name }}" ), }, { "path": "Dockerfile", "type": "dockerfile", "content": ( "FROM python:3.11-slim\n" "WORKDIR /app\n" "COPY . .\n" 'CMD ["python", "app.py"]' ), }, ], "error": { "phase": "push", "message": ( "denied: permission_denied: write_package — " "GITHUB_TOKEN does not have packages:write permission" ), "exit_code": 1, "failed_step": "Build and push", }, "expected_fixes": [ { "file": ".github/workflows/publish.yml", "type": "contains", "expected": "packages: write", "hint": "Add 'permissions: packages: write' at job or workflow level to allow pushing to GHCR", }, ], }, # Scenario 4: Secret referenced in run but not mapped to env { "id": "secret_not_in_env", "files": [ { "path": ".github/workflows/notify.yml", "type": "workflow", "content": ( "name: Notify\n" "on:\n" " push:\n" " branches: [main]\n" "\n" "jobs:\n" " notify:\n" " runs-on: ubuntu-latest\n" " steps:\n" " - uses: actions/checkout@v4\n" " - name: Send Slack notification\n" " run: |\n" " curl -X POST -H 'Content-Type: application/json' \\\n" " -d '{\"text\": \"Deployed ${{ github.sha }}\"}' \\\n" " $SLACK_WEBHOOK_URL" ), }, ], "error": { "phase": "workflow_parse", "message": "SLACK_WEBHOOK_URL is empty — secret not available in shell environment", "exit_code": 1, "failed_step": "Send Slack notification", }, "expected_fixes": [ { "file": ".github/workflows/notify.yml", "type": "contains", "expected": "SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}", "hint": "Map the secret to an environment variable using env: block", }, ], }, # Scenario 5: Using DOCKER_PASSWORD for GHCR instead of GITHUB_TOKEN { "id": "ghcr_wrong_credentials", "files": [ { "path": ".github/workflows/ghcr.yml", "type": "workflow", "content": ( "name: Push to GHCR\n" "on:\n" " push:\n" " branches: [main]\n" "\n" "jobs:\n" " push:\n" " runs-on: ubuntu-latest\n" " permissions:\n" " packages: write\n" " steps:\n" " - uses: actions/checkout@v4\n" " - name: Login to GHCR\n" " run: echo ${{ secrets.DOCKER_PASSWORD }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin\n" " - name: Push image\n" " run: |\n" " docker build -t ghcr.io/${{ github.repository }}:latest .\n" " docker push ghcr.io/${{ github.repository }}:latest" ), }, { "path": "Dockerfile", "type": "dockerfile", "content": ( "FROM python:3.11-slim\n" "WORKDIR /app\n" "COPY . .\n" 'CMD ["python", "app.py"]' ), }, ], "error": { "phase": "push", "message": ( "Error: denied: installation not allowed to Create organization package — " "GHCR requires GITHUB_TOKEN, not DOCKER_PASSWORD" ), "exit_code": 1, "failed_step": "Login to GHCR", }, "expected_fixes": [ { "file": ".github/workflows/ghcr.yml", "type": "contains", "expected": "secrets.GITHUB_TOKEN", "hint": "GHCR uses GITHUB_TOKEN for authentication, not DOCKER_PASSWORD", }, ], }, ]