Skip to content

Commit 80d0159

Browse files
committed
docs(skills): add enhancements to security, testcontainers, testing-strategy
- static-analysis-security: Add sample suppression entries and evidence capture guidance (#352) - testcontainers-integration-tests: Add sample CI run logs and container lifecycle checklist (#354) - testing-strategy-dotnet: Add example solution structure and sample CI matrix (#356) Refs: #352, #354, #356
1 parent 634470d commit 80d0159

File tree

4 files changed

+818
-1
lines changed

4 files changed

+818
-1
lines changed

cspell.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,11 @@
268268
"CIEOF",
269269
"conftest",
270270
"Exploitability",
271-
"Requestor"
271+
"isready",
272+
"Requestor",
273+
"semgrepignore",
274+
"testdata",
275+
"testpass"
272276
],
273277
"ignorePaths": ["node_modules/**", "package-lock.json"]
274278
}

skills/static-analysis-security/SKILL.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

162343
Load based on specific need:

0 commit comments

Comments
 (0)