-
Notifications
You must be signed in to change notification settings - Fork 29
Add security scan file for vulnerability scans #1039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| name: Shared Setup | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| go-version: '1.22' | ||
| steps: | ||
| - name: Checkout Code | ||
| uses: actions/checkout@v4 | ||
| - name: Export Go Version | ||
| run: echo "go-version=1.22" >> $GITHUB_OUTPUT | ||
|
|
||
| gosec_scan: |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 months ago
To fix the problem, explicitly limit the permissions of the GITHUB_TOKEN for the setup job by adding a permissions block. Since the job only checks out code and sets outputs (with no repository writes or PR interaction), setting its permissions to contents: read is sufficient and adheres to least privilege.
Edit Details:
- File:
.github/workflows/security.yml - Region: Job definition starting at line 12 (
setup:) - Insert
permissions:block directly under line 13 (aftername: Shared Setup) - Set permissions as follows:
permissions: contents: read - No new imports or methods needed. Only this change to the YAML block.
-
Copy modified lines R14-R15
| @@ -11,6 +11,8 @@ | ||
| jobs: | ||
| setup: | ||
| name: Shared Setup | ||
| permissions: | ||
| contents: read | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| go-version: '1.22' |
| name: Vulnerability Summary Report | ||
| needs: [gosec_scan, trivy_scan] | ||
| runs-on: ubuntu-latest | ||
| if: github.event_name == 'pull_request' && always() | ||
| steps: | ||
| - name: Create Vulnerability Summary Comment | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const gosecCurrent = '${{ needs.gosec_scan.outputs.gosec_current_count }}' || '0'; | ||
| const gosecBaseline = '${{ needs.gosec_scan.outputs.gosec_baseline_count }}' || '0'; | ||
| const gosecAdded = '${{ needs.gosec_scan.outputs.gosec_added_count }}' || '0'; | ||
| const gosecFixed = '${{ needs.gosec_scan.outputs.gosec_fixed_count }}' || '0'; | ||
|
|
||
| const trivyCurrent = '${{ needs.trivy_scan.outputs.trivy_current_count }}' || '0'; | ||
| const trivyBaseline = '${{ needs.trivy_scan.outputs.trivy_baseline_count }}' || '0'; | ||
| const trivyAdded = '${{ needs.trivy_scan.outputs.trivy_added_count }}' || '0'; | ||
| const trivyFixed = '${{ needs.trivy_scan.outputs.trivy_fixed_count }}' || '0'; | ||
|
|
||
| const trivyImageCurrent = '${{ needs.trivy_scan.outputs.trivy_image_current_count }}' || '0'; | ||
| const trivyImageBaseline = '${{ needs.trivy_scan.outputs.trivy_image_baseline_count }}' || '0'; | ||
| const trivyImageAdded = '${{ needs.trivy_scan.outputs.trivy_image_added_count }}' || '0'; | ||
| const trivyImageFixed = '${{ needs.trivy_scan.outputs.trivy_image_fixed_count }}' || '0'; | ||
|
|
||
| const gosecMethod = '${{ needs.gosec_scan.outputs.gosec_baseline_method }}' || 'none'; | ||
| const trivyMethod = '${{ needs.trivy_scan.outputs.trivy_baseline_method }}' || 'none'; | ||
| const trivyImageMethod = '${{ needs.trivy_scan.outputs.trivy_image_baseline_method }}' || 'none'; | ||
|
|
||
| // Get detailed vulnerability information (safely encoded) | ||
| const gosecAddedDetails = ${{ toJSON(needs.gosec_scan.outputs.gosec_added_details) }} || ''; | ||
| const gosecFixedDetails = ${{ toJSON(needs.gosec_scan.outputs.gosec_fixed_details) }} || ''; | ||
| const trivyAddedDetails = ${{ toJSON(needs.trivy_scan.outputs.trivy_added_details) }} || ''; | ||
| const trivyFixedDetails = ${{ toJSON(needs.trivy_scan.outputs.trivy_fixed_details) }} || ''; | ||
| const trivyImageAddedDetails = ${{ toJSON(needs.trivy_scan.outputs.trivy_image_added_details) }} || ''; | ||
| const trivyImageFixedDetails = ${{ toJSON(needs.trivy_scan.outputs.trivy_image_fixed_details) }} || ''; | ||
|
|
||
| const totalAdded = parseInt(gosecAdded) + parseInt(trivyAdded) + parseInt(trivyImageAdded); | ||
| const totalFixed = parseInt(gosecFixed) + parseInt(trivyFixed) + parseInt(trivyImageFixed); | ||
| const totalCurrent = parseInt(gosecCurrent) + parseInt(trivyCurrent) + parseInt(trivyImageCurrent); | ||
| const totalBaseline = parseInt(gosecBaseline) + parseInt(trivyBaseline) + parseInt(trivyImageBaseline); | ||
|
|
||
| // Method indicators | ||
| const getMethodIcon = (method) => { | ||
| switch(method) { | ||
| case 'artifact': return '📦'; | ||
| case 'live_scan': return '🔄'; | ||
| case 'no_baseline': return '⚠️'; | ||
| default: return '❓'; | ||
| } | ||
| }; | ||
|
|
||
| let statusIcon = '✅'; | ||
| let statusText = 'No change in security posture'; | ||
|
|
||
| if (totalAdded > 0 && totalFixed === 0) { | ||
| statusIcon = '🚨'; | ||
| statusText = 'Security posture degraded'; | ||
| } else if (totalAdded === 0 && totalFixed > 0) { | ||
| statusIcon = '🎉'; | ||
| statusText = 'Security posture improved'; | ||
| } else if (totalAdded > 0 && totalFixed > 0) { | ||
| statusIcon = '⚠️'; | ||
| statusText = 'Mixed security changes'; | ||
| } | ||
|
|
||
| const comment = `## ${statusIcon} Security Vulnerability Summary | ||
|
|
||
| **${statusText}** | ||
|
|
||
| ### 📊 Overall Changes | ||
| | Metric | Count | | ||
| |--------|-------| | ||
| | **Total Added** | **${totalAdded}** | | ||
| | **Total Fixed** | **${totalFixed}** | | ||
| | **Net Change** | **${totalAdded - totalFixed > 0 ? '+' : ''}${totalAdded - totalFixed}** | | ||
|
|
||
| ### 🔍 Detailed Breakdown | ||
|
|
||
| #### ${getMethodIcon(gosecMethod)} Gosec (Static Analysis) | ||
| | Current | Baseline | Added | Fixed | Method | | ||
| |---------|----------|-------|-------|--------| | ||
| | ${gosecCurrent} | ${gosecBaseline} | ${gosecAdded} | ${gosecFixed} | ${gosecMethod} | | ||
|
|
||
| #### ${getMethodIcon(trivyMethod)} Trivy (Dependency Scan) | ||
| | Current | Baseline | Added | Fixed | Method | | ||
| |---------|----------|-------|-------|--------| | ||
| | ${trivyCurrent} | ${trivyBaseline} | ${trivyAdded} | ${trivyFixed} | ${trivyMethod} | | ||
|
|
||
| #### ${getMethodIcon(trivyImageMethod)} Trivy (Docker Images) | ||
| | Current | Baseline | Added | Fixed | Method | | ||
| |---------|----------|-------|-------|--------| | ||
| | ${trivyImageCurrent} | ${trivyImageBaseline} | ${trivyImageAdded} | ${trivyImageFixed} | ${trivyImageMethod} | | ||
|
|
||
| ### 📋 Baseline Methods | ||
| - **📦 artifact**: Used stored report from main branch | ||
| - **🔄 live_scan**: Scanned base branch in real-time | ||
| - **⚠️ no_baseline**: No baseline available (all vulnerabilities treated as new) | ||
|
|
||
| ${totalAdded > 0 ? ` | ||
| ### 🚨 Added Vulnerabilities | ||
|
|
||
| ${parseInt(gosecAdded) > 0 ? ` | ||
| #### Gosec (Static Analysis) - ${gosecAdded} Added | ||
| ${gosecAddedDetails || '*No detailed information available*'} | ||
| ` : ''} | ||
|
|
||
| ${parseInt(trivyAdded) > 0 ? ` | ||
| #### Trivy (Dependencies) - ${trivyAdded} Added | ||
| ${trivyAddedDetails || '*No detailed information available*'} | ||
| ` : ''} | ||
|
|
||
| ${parseInt(trivyImageAdded) > 0 ? ` | ||
| #### Trivy (Docker Images) - ${trivyImageAdded} Added | ||
| ${trivyImageAddedDetails || '*No detailed information available*'} | ||
| ` : ''} | ||
| ` : ''} | ||
|
|
||
| ${totalFixed > 0 ? ` | ||
| ### 🎉 Fixed Vulnerabilities | ||
|
|
||
| ${parseInt(gosecFixed) > 0 ? ` | ||
| #### Gosec (Static Analysis) - ${gosecFixed} Fixed | ||
| ${gosecFixedDetails || '*No detailed information available*'} | ||
| ` : ''} | ||
|
|
||
| ${parseInt(trivyFixed) > 0 ? ` | ||
| #### Trivy (Dependencies) - ${trivyFixed} Fixed | ||
| ${trivyFixedDetails || '*No detailed information available*'} | ||
| ` : ''} | ||
|
|
||
| ${parseInt(trivyImageFixed) > 0 ? ` | ||
| #### Trivy (Docker Images) - ${trivyImageFixed} Fixed | ||
| ${trivyImageFixedDetails || '*No detailed information available*'} | ||
| ` : ''} | ||
| ` : ''} | ||
|
|
||
| --- | ||
| *Only HIGH and CRITICAL severity vulnerabilities are tracked* | ||
| *Baseline: \`${{ github.event.pull_request.base.sha }}\`*`; | ||
|
|
||
| github.rest.issues.createComment({ | ||
| issue_number: context.issue.number, | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| body: comment | ||
| }); No newline at end of file |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 2 months ago
To fix the problem, add a permissions block to the vulnerability_summary job in .github/workflows/security.yml, just beneath the runs-on: ubuntu-latest and above the steps: key. This block should grant only the minimal permissions necessary for the steps performed by the job. In this case, the only relevant step is posting a comment to a PR via the actions/github-script, so contents: read and pull-requests: write would be appropriate minimal permissions (alternatively, if Issue comments might be used, include issues: write). No imports or further code changes are needed.
-
Copy modified lines R628-R630
| @@ -625,6 +625,9 @@ | ||
| name: Vulnerability Summary Report | ||
| needs: [gosec_scan, trivy_scan] | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
| if: github.event_name == 'pull_request' && always() | ||
| steps: | ||
| - name: Create Vulnerability Summary Comment |
✅ Security Vulnerability SummaryNo change in security posture 📊 Overall Changes
🔍 Detailed Breakdown🔄 Gosec (Static Analysis)
🔄 Trivy (Dependency Scan)
|
| Current | Baseline | Added | Fixed | Method |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | no_baseline |
📋 Baseline Methods
- 📦 artifact: Used stored report from main branch
- 🔄 live_scan: Scanned base branch in real-time
⚠️ no_baseline: No baseline available (all vulnerabilities treated as new)
Only HIGH and CRITICAL severity vulnerabilities are tracked
Baseline: 11b1ee2b7620455795b3370cd3cbe2f25881796e
✅ Security Vulnerability SummaryNo change in security posture 📊 Overall Changes
🔍 Detailed Breakdown🔄 Gosec (Static Analysis)
🔄 Trivy (Dependency Scan)
📋 Baseline Methods
Only HIGH and CRITICAL severity vulnerabilities are tracked |
bf6ece6 to
ec68bf6
Compare
✅ Security Vulnerability SummaryNo change in security posture 📊 Overall Changes
🔍 Detailed Breakdown🔄 Gosec (Static Analysis)
🔄 Trivy (Dependency Scan)
📋 Baseline Methods
Only HIGH and CRITICAL severity vulnerabilities are tracked |
|
go through the last summary report. The summary will be like this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 To request another review, post a new comment with "/windsurf-review".
| go-version: '1.22' | ||
| steps: | ||
| - name: Checkout Code | ||
| uses: actions/checkout@v4 | ||
| - name: Export Go Version | ||
| run: echo "go-version=1.22" >> $GITHUB_OUTPUT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Go version is hardcoded in both the output and the echo command. This creates a maintenance issue if the version needs to be updated. Consider using a single variable:
| go-version: '1.22' | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: Export Go Version | |
| run: echo "go-version=1.22" >> $GITHUB_OUTPUT | |
| go-version: ${{ vars.GO_VERSION || '1.22' }} | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| - name: Export Go Version | |
| run: echo "go-version=${{ vars.GO_VERSION || '1.22' }}" >> $GITHUB_OUTPUT |
.github/workflows/security.yml
Outdated
| branches: | ||
| - main | ||
| - harsh/soc2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workflow is configured to run on a specific developer branch 'harsh/soc2'. For security workflows, it's better to limit triggers to main branches and PRs to avoid unnecessary runs and potential security information leakage. Consider removing this specific branch from the triggers.
|
|
||
| - name: Create Pull Request (if vulnerabilities found) | ||
| if: ${{ github.event_name == 'push' && steps.scan.outputs.gosec_high_found == 'true' }} | ||
| continue-on-error: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'Create Pull Request' steps for both Gosec and Trivy use 'continue-on-error: true', which means failures in creating security vulnerability reports will be silently ignored. For critical security operations, consider removing this option or adding explicit error handling to ensure security issues are properly reported.
✅ Security Vulnerability SummaryNo change in security posture 📊 Overall Changes
🔍 Detailed Breakdown🔄 Gosec (Static Analysis)
🔄 Trivy (Dependency Scan)
📋 Baseline Methods
Only HIGH and CRITICAL severity vulnerabilities are tracked |
What this PR does / why we need it
This PR contains the vulnerability scanning in the codebase. It will scan the vulnerabilities in the codebase in this PR you can see the the summary report. When this PR will be merged to main, it will scan the main branch raise a report in form of PR in the pull requests and also store the report as artifact. Then in next PR it will scan the code changes and will tell in the summary how many vulnerabilities are fixed and how many are added. Also show the details that which vulnerabilities are added and fixed respectively.
Which issue(s) this PR fixes
(optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)format, will close the issue(s) when PR gets merged)fixes #
Special notes for your reviewer
Also for the scan in a particular PR, it will compare with the artifact if it is present on main branch and on method in the summary it will show as artifact and if the artifact is not present then the comparison will happen with live scan first scanning the code before the commits from the base branch and then scan with the committed code and generate the comparison.
Testing done
please add testing details (logs, screenshots, etc.)