|
64 | 64 | include: |
65 | 65 | - language: actions |
66 | 66 | build-mode: none |
67 | | - - language: yaml |
68 | | - build-mode: none |
69 | 67 | steps: |
70 | 68 | - name: Checkout |
71 | 69 | uses: actions/checkout@v4 |
@@ -119,62 +117,111 @@ jobs: |
119 | 117 | load: true |
120 | 118 | tags: irc-atl-chat-${{ matrix.service }}:security-scan |
121 | 119 | - name: Scan Container Image |
122 | | - uses: aquasecurity/trivy-action@master |
123 | | - with: |
124 | | - image-ref: 'irc-atl-chat-${{ matrix.service }}:security-scan' |
125 | | - format: 'sarif' |
126 | | - output: 'trivy-results-${{ matrix.service }}.sarif' |
127 | | - severity: 'HIGH,CRITICAL' |
128 | | - - name: Upload Trivy scan results to GitHub Security tab |
129 | | - uses: github/codeql-action/upload-sarif@v3 |
130 | | - with: |
131 | | - sarif_file: 'trivy-results-${{ matrix.service }}.sarif' |
132 | | - category: trivy-${{ matrix.service }} |
133 | | - - name: Upload Results |
134 | | - if: always() |
135 | | - uses: actions/upload-artifact@v4 |
| 120 | + |
136 | 121 | with: |
137 | | - name: trivy-results-${{ matrix.service }} |
138 | | - path: trivy-results-${{ matrix.service }}.sarif |
139 | | - retention-days: 30 |
140 | | - secrets: |
141 | | - name: Secret Detection |
| 122 | + github_token: ${{ secrets.GITHUB_TOKEN }} |
| 123 | + trivy_command: image |
| 124 | + trivy_target: 'irc-atl-chat-${{ matrix.service }}:security-scan' |
| 125 | + level: warning |
| 126 | + reporter: github-pr-review |
| 127 | + tool_name: trivy-${{ matrix.service }} |
| 128 | + filter_mode: nofilter |
| 129 | + fail_level: none |
| 130 | + trivy_flags: --severity HIGH,CRITICAL --exit-code 0 |
| 131 | + shell: |
| 132 | + name: Shell Script Security |
142 | 133 | runs-on: ubuntu-latest |
143 | 134 | needs: [changes] |
144 | | - if: always() |
| 135 | + if: (needs.changes.outputs.shell == 'true' || github.event_name == 'workflow_dispatch') |
145 | 136 | permissions: |
146 | 137 | contents: read |
147 | 138 | security-events: write |
148 | 139 | steps: |
149 | 140 | - name: Checkout |
150 | 141 | uses: actions/checkout@v4 |
151 | | - - name: Scan for Secrets |
152 | | - uses: trufflesecurity/trufflehog@main |
153 | | - with: |
154 | | - path: ./ |
155 | | - base: main |
156 | | - head: HEAD |
157 | | - extra_args: --debug --only-verified |
158 | | - - name: Upload Results |
159 | | - if: always() |
160 | | - uses: actions/upload-artifact@v4 |
161 | | - with: |
162 | | - name: trufflehog-results |
163 | | - path: trufflehog-results.json |
164 | | - retention-days: 30 |
165 | | - dependabot: |
166 | | - name: Dependabot |
167 | | - runs-on: ubuntu-latest |
168 | | - if: github.actor == 'dependabot[bot]' |
169 | | - permissions: |
170 | | - contents: write |
171 | | - pull-requests: write |
172 | | - steps: |
173 | | - - name: Checkout |
174 | | - uses: actions/checkout@v4 |
175 | | - - name: Auto-merge |
| 142 | + - name: Shell Script Security Analysis |
176 | 143 | run: | |
177 | | - gh pr merge --auto --merge "$PR_URL" || echo "Auto-merge failed, manual review required" |
178 | | - env: |
179 | | - PR_URL: ${{ github.event.pull_request.html_url }} |
180 | | - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 144 | + echo "## 🔍 Shell Script Security Analysis" |
| 145 | + echo "" |
| 146 | + |
| 147 | + # Find all shell scripts |
| 148 | + SHELL_SCRIPTS=$(find . -name "*.sh" -o -name "*.bash" -o -name "*.zsh" | grep -v ".git" || echo "") |
| 149 | + |
| 150 | + if [ -z "$SHELL_SCRIPTS" ]; then |
| 151 | + echo "No shell scripts found for analysis" |
| 152 | + exit 0 |
| 153 | + fi |
| 154 | + |
| 155 | + echo "Found shell scripts:" |
| 156 | + echo "$SHELL_SCRIPTS" |
| 157 | + echo "" |
| 158 | + |
| 159 | + # Security checks for shell scripts |
| 160 | + for script in $SHELL_SCRIPTS; do |
| 161 | + echo "### Analyzing: $script" |
| 162 | + |
| 163 | + # Check for common security issues |
| 164 | + echo "**Security Checks:**" |
| 165 | + |
| 166 | + # Check for hardcoded passwords/secrets |
| 167 | + if grep -n -i "password\|secret\|key\|token" "$script" | grep -v "#.*password\|#.*secret" | grep -v "echo.*password\|echo.*secret"; then |
| 168 | + echo "⚠️ Potential hardcoded credentials found" |
| 169 | + else |
| 170 | + echo "✅ No obvious hardcoded credentials" |
| 171 | + fi |
| 172 | + |
| 173 | + # Check for eval usage (dangerous) |
| 174 | + if grep -n "eval " "$script"; then |
| 175 | + echo "⚠️ Use of 'eval' detected (security risk)" |
| 176 | + else |
| 177 | + echo "✅ No 'eval' usage found" |
| 178 | + fi |
| 179 | + |
| 180 | + # Check for unquoted variables |
| 181 | + if grep -n "\$[a-zA-Z_][a-zA-Z0-9_]*[^\"' ]" "$script" | grep -v "echo\|printf\|test"; then |
| 182 | + echo "⚠️ Potentially unquoted variables found" |
| 183 | + else |
| 184 | + echo "✅ Variables appear properly quoted" |
| 185 | + fi |
| 186 | + |
| 187 | + # Check for rm -rf patterns |
| 188 | + if grep -n "rm.*-rf" "$script"; then |
| 189 | + echo "⚠️ 'rm -rf' usage detected (verify paths are safe)" |
| 190 | + else |
| 191 | + echo "✅ No dangerous rm patterns" |
| 192 | + fi |
| 193 | + |
| 194 | + # Check for curl/wget without SSL verification |
| 195 | + if grep -n "curl.*-k\|wget.*--no-check-certificate" "$script"; then |
| 196 | + echo "⚠️ SSL verification disabled in network requests" |
| 197 | + else |
| 198 | + echo "✅ SSL verification appears enabled" |
| 199 | + fi |
| 200 | + |
| 201 | + echo "" |
| 202 | + done |
| 203 | + { |
| 204 | + echo "## 🛡️ Additional Security Analysis" |
| 205 | + echo "" |
| 206 | + |
| 207 | + # Check for dangerous file permissions |
| 208 | + echo "**File Permission Analysis:**" |
| 209 | + DANGEROUS_PERMS=$(find . -type f -perm /o+w -not -path "./.git/*" 2>/dev/null || echo "") |
| 210 | + if [ -n "$DANGEROUS_PERMS" ]; then |
| 211 | + echo "⚠️ World-writable files found:" |
| 212 | + echo "$DANGEROUS_PERMS" |
| 213 | + else |
| 214 | + echo "✅ No world-writable files found" |
| 215 | + fi |
| 216 | + |
| 217 | + # Check for suid/sgid files |
| 218 | + SUID_FILES=$(find . -type f \( -perm -4000 -o -perm -2000 \) -not -path "./.git/*" 2>/dev/null || echo "") |
| 219 | + if [ -n "$SUID_FILES" ]; then |
| 220 | + echo "⚠️ SUID/SGID files found:" |
| 221 | + echo "$SUID_FILES" |
| 222 | + else |
| 223 | + echo "✅ No SUID/SGID files found" |
| 224 | + fi |
| 225 | + |
| 226 | + echo "" |
| 227 | + } >> "$GITHUB_STEP_SUMMARY" |
0 commit comments