@@ -157,6 +157,187 @@ These statements indicate security analysis gaps:
157157
158158**All mean:** Apply this skill properly or document explicit opt-out with risk acceptance.
159159
160+ ## Sample Suppression Entries
161+
162+ ### ESLint Security Suppressions
163+
164+ ` ` ` javascript
165+ // GOOD : Specific, justified, linked to ticket
166+ // eslint-disable-next-line security/detect-object-injection -- Index validated against allowlist per SEC-123
167+ const value = obj[sanitizedKey];
168+
169+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- Path validated from config, not user input
170+ const config = fs.readFileSync(configPath);
171+
172+ // BAD : Vague, no justification
173+ // eslint-disable-next-line security/detect-object-injection
174+ const value = obj[key];
175+ ```
176+
177+ ### Bandit Suppressions (Python)
178+
179+ ``` python
180+ # GOOD: Specific reason, ticket reference
181+ # nosec B105 - Placeholder constant for testing, replaced at runtime. See SEC-456
182+ TEST_TOKEN_PLACEHOLDER = " REPLACE_WITH_REAL_TOKEN"
183+
184+ # nosec B608 - SQL query uses parameterized values, table name from enum only
185+ query = f " SELECT * FROM { TableName.USERS .value} WHERE id = %s "
186+
187+ # BAD: No explanation
188+ password = " admin123" # nosec
189+ ```
190+
191+ ### Semgrep Suppressions
192+
193+ ``` yaml
194+ # In code (inline):
195+ # nosemgrep: javascript.express.security.audit.xss.mustache-escape
196+
197+ # In .semgrepignore file:
198+ # Ignore test fixtures
199+ tests/fixtures/**
200+
201+ # In semgrep config (.semgrep.yml):
202+ rules :
203+ - id : custom-rule
204+ paths :
205+ exclude :
206+ - " *_test.go"
207+ - " testdata/**"
208+ ` ` `
209+
210+ ### CodeQL Suppressions (via SARIF)
211+
212+ ` ` ` yaml
213+ # codeql-config.yml
214+ paths-ignore :
215+ - tests/**
216+ - " **/testdata/**"
217+ query-filters :
218+ - exclude :
219+ id : js/unused-local-variable
220+ # Only exclude in test files
221+ paths : " **/*.test.js"
222+ ` ` `
223+
224+ ### Suppression Tracking Template
225+
226+ ` ` ` markdown
227+ # # Security Suppression Log
228+
229+ | ID | Tool | Rule | File | Justification | Owner | Expiry | Ticket |
230+ | ------- | ------- | ----------------------- | ------------ | ---------------- | ----- | ---------- | ------- |
231+ | SUP-001 | Bandit | B105 | config.py:42 | Test placeholder | @dev | 2025-03-01 | SEC-123 |
232+ | SUP-002 | Semgrep | xss-audit | api.ts:156 | Sanitized output | @lead | N/A (FP) | N/A |
233+ | SUP-003 | ESLint | detect-object-injection | util.js:89 | Validated index | @dev | 2025-04-15 | SEC-456 |
234+ ```
235+
236+ ## Evidence Capture Guidance
237+
238+ ### Scan Evidence Template
239+
240+ ```` markdown
241+ ## Security Scan Evidence
242+
243+ ** Date** : YYYY-MM-DD
244+ ** Commit** : abc1234
245+ ** Branch** : feature/xyz
246+ ** Scanner Version** : [ tool@version]
247+
248+ ### Summary
249+
250+ | Severity | Count | Status |
251+ | -------- | ----- | ---------------------- |
252+ | Critical | 0 | Pass |
253+ | High | 2 | Blocked (requires fix) |
254+ | Medium | 5 | Baselined |
255+ | Low | 12 | Info only |
256+
257+ ### New Findings
258+
259+ | ID | Severity | Rule | Location | Status |
260+ | ---- | -------- | ------------- | ----------------- | ------------ |
261+ | F001 | High | sql-injection | api/query.ts:45 | Fix required |
262+ | F002 | High | xss-reflected | web/render.ts:123 | Fix required |
263+
264+ ### Baselined Findings
265+
266+ | ID | Severity | Baseline Date | Review Date | Ticket |
267+ | ---- | -------- | ------------- | ----------- | ------- |
268+ | B001 | Medium | 2024-12-01 | 2025-03-01 | SEC-789 |
269+ | B002 | Medium | 2024-12-01 | 2025-03-01 | SEC-790 |
270+
271+ ### Verification
272+
273+ ``` bash
274+ # Commands run
275+ semgrep --config=p/security-audit --sarif -o results.sarif .
276+ bandit -r src/ -f sarif -o bandit.sarif
277+ gitleaks detect --source . --report-format sarif --report-path secrets.sarif
278+ ```
279+ ````
280+
281+ ### CI Pipeline Evidence
282+
283+ ``` yaml
284+ # GitHub Actions example with evidence artifacts
285+ security-scan :
286+ runs-on : ubuntu-latest
287+ steps :
288+ - uses : actions/checkout@v4
289+
290+ - name : Run Semgrep
291+ uses : returntocorp/semgrep-action@v1
292+ with :
293+ config : p/security-audit
294+ generateSarif : true
295+
296+ - name : Run Gitleaks
297+ uses : gitleaks/gitleaks-action@v2
298+ with :
299+ report_format : sarif
300+
301+ - name : Upload SARIF results
302+ uses : github/codeql-action/upload-sarif@v3
303+ with :
304+ sarif_file : results/
305+
306+ - name : Archive scan evidence
307+ uses : actions/upload-artifact@v4
308+ with :
309+ name : security-scan-evidence-${{ github.sha }}
310+ path : |
311+ results/*.sarif
312+ results/*.json
313+ retention-days : 90
314+ ` ` `
315+
316+ ### Evidence Retention Requirements
317+
318+ | Evidence Type | Retention | Storage |
319+ | ------------------ | --------------- | ----------------- |
320+ | SARIF reports | 90 days minimum | CI artifacts |
321+ | Suppression log | Permanent | Repository |
322+ | Baseline snapshots | Per release | Release artifacts |
323+ | Audit trail | 1 year | Compliance system |
324+
325+ ### Verification Commands
326+
327+ ` ` ` bash
328+ # Verify SARIF output is valid
329+ cat results.sarif | jq '.runs[0].results | length'
330+
331+ # Check for unaddressed critical/high findings
332+ jq '[.runs[].results[] | select(.level == "error")] | length' results.sarif
333+
334+ # Verify no secrets in scan scope
335+ gitleaks detect --source . --verbose --no-git
336+
337+ # Compare against baseline
338+ semgrep --config=p/security-audit --baseline-commit HEAD~1 .
339+ ```
340+
160341## Reference Documents
161342
162343Load based on specific need:
0 commit comments