DevSecOps patterns — shift-left security, SAST (semgrep/CodeQL), secrets detection (gitleaks/trufflehog), dependency scanning (trivy/grype), DAST, OPA/Falco policy-as-code, container security, and security gates per CI stage.
From clarcnpx claudepluginhub marvinrichter/clarc --plugin clarcThis skill uses the workspace's default tool permissions.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
DevSecOps integrates security into every phase of the SDLC — shifting left from post-release penetration tests to pre-commit hooks and PR gates. Security is continuous, automated, developer-friendly, and not a final checkpoint.
Pre-commit hook → < 5 seconds (Gitleaks, fast Semgrep rules)
PR Gate → < 5 minutes (Trivy, full Semgrep, ZAP Baseline)
Pre-Release Gate → < 30 minutes (Full DAST, license scan, SBOM)
One engineer per product team acts as the Security Champion:
# Run with auto-selected rules (best for most projects)
semgrep --config=auto .
# Run only on changed files (fast for pre-commit)
git diff --name-only HEAD | xargs semgrep --config=auto
# .semgrep/rules/no-hardcoded-secrets.yaml
rules:
- id: no-hardcoded-api-key
patterns:
- pattern: |
$KEY = "..."
- metavariable-regex:
metavariable: $KEY
regex: '(?i)(api_key|apikey|secret|password|token|auth)'
- metavariable-regex:
metavariable: $VALUE
regex: '[A-Za-z0-9+/]{20,}'
message: "Potential hardcoded secret in variable $KEY"
severity: ERROR
languages: [python, javascript, typescript, go, java]
metadata:
category: security
cwe: "CWE-798"
owasp: "A02:2021"
# .github/workflows/sast.yml
jobs:
semgrep:
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- run: |
semgrep ci --config=auto --severity ERROR --error \
--sarif-output=semgrep-results.sarif
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: semgrep-results.sarif
codeql:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with:
languages: javascript, python
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
| Language | Tool | Command |
|---|---|---|
| Python | Bandit | bandit -r src/ -ll |
| Go | gosec | gosec ./... |
| Ruby | Brakeman | brakeman -q -w2 . |
| JavaScript | ESLint security | eslint --plugin security src/ |
| Java | SpotBugs + FindSecBugs | mvn spotbugs:check |
# Scan only staged files (fast pre-commit check)
gitleaks protect --staged
# Scan git history (finds secrets committed in the past)
gitleaks detect --source=. --log-opts="--all" --verbose
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
entry: gitleaks protect --staged -v
pass_filenames: false
# .gitleaks.toml
[extend]
useDefault = true
[[rules]]
description = "Internal API Key"
id = "internal-api-key"
regex = '''MYAPP_[A-Z0-9]{32}'''
[allowlist]
regexes = ["test-api-key-12345"]
paths = [".git", "tests/fixtures/", "*.test.ts"]
# Scan entire git history
trufflehog git file://. --since-commit HEAD~100 --only-verified
# Scan a GitHub org's repos
trufflehog github --org=myorg --token=$GITHUB_TOKEN
When a secret is discovered in Git:
git push --force-with-lease# Scan filesystem (dependencies + IaC misconfigurations)
trivy fs . --severity HIGH,CRITICAL
# Scan container image, fail on CRITICAL (for CI gate)
trivy image myorg/my-app:latest --severity CRITICAL --exit-code 1
# Generate SBOM
trivy fs . --format spdx-json --output sbom.json
- uses: aquasecurity/trivy-action@master
with:
image-ref: myorg/my-app:${{ github.sha }}
format: sarif
output: trivy-results.sarif
severity: HIGH,CRITICAL
exit-code: '1'
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: trivy-results.sarif
npm audit --audit-level=high # Node.js
pip-audit -r requirements.txt # Python
govulncheck ./... # Go
cargo audit # Rust
bundle exec bundle-audit check # Ruby
The Baseline Scan only performs passive scanning — it does not modify data. Safe to run against any environment.
docker run --rm \
-v $(pwd):/zap/wrk \
ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py \
-t http://my-app:8080 \
-r zap-report.html \
-J zap-report.json \
-I # Don't fail on warnings, only errors
- name: Start app
run: docker compose up -d
- name: Wait for app to be ready
run: timeout 60 bash -c 'until curl -sf http://localhost:8080/health; do sleep 2; done'
- name: OWASP ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.12.0
with:
target: 'http://localhost:8080'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-I'
fail_action: false
- uses: actions/upload-artifact@v4
with:
name: zap-report
path: report_html.html
# Active scan — CAN modify data, only run in dedicated test environment
docker run --rm \
-v $(pwd):/zap/wrk \
ghcr.io/zaproxy/zaproxy:stable \
zap-full-scan.py \
-t http://test-app:8080 \
-r full-scan-report.html \
-z "-config scanner.attackStrength=HIGH"
# ConstraintTemplate — define the policy
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: requirelabels
spec:
crd:
spec:
names:
kind: RequireLabels
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package requirelabels
violation[{"msg": msg}] {
required := {label | label := input.parameters.labels[_]}
provided := {label | input.review.object.metadata.labels[label]}
missing := required - provided
count(missing) > 0
msg := sprintf("Missing required labels: %v", [missing])
}
---
# Constraint — apply the policy
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: RequireLabels
metadata:
name: require-pod-labels
spec:
match:
kinds: [{apiGroups: [""], kinds: ["Pod"]}]
namespaces: ["production", "staging"]
parameters:
labels: ["app", "team", "version"]
# Write a Rego policy
cat > policy/no-root.rego << 'EOF'
package main
deny[msg] {
input.kind == "Deployment"
container := input.spec.template.spec.containers[_]
not container.securityContext.runAsNonRoot
msg := sprintf("Container '%s' must set runAsNonRoot: true", [container.name])
}
EOF
conftest test k8s/ --policy policy/
# /etc/falco/rules.d/custom-rules.yaml
- rule: Suspicious shell in container
desc: Detect shell spawned in a container
condition: >
spawned_process and container
and proc.name in (shell_binaries)
and not proc.pname in (known_shell_spawn_binaries)
output: >
Shell spawned in container (user=%user.name container=%container.name
image=%container.image.repository proc=%proc.name parent=%proc.pname)
priority: WARNING
tags: [container, shell, T1059]
- rule: Write to sensitive directory
desc: Detect writes to /etc or /usr in containers
condition: >
open_write and container
and (fd.directory startswith /etc or fd.directory startswith /usr/bin)
output: >
Sensitive file write (user=%user.name file=%fd.name
container=%container.name image=%container.image.repository)
priority: ERROR
tags: [container, filesystem, T1222]
# Multi-stage build — don't ship build tools
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json .
RUN npm ci --only=production
# Use distroless for minimal attack surface
FROM gcr.io/distroless/nodejs22-debian12:nonroot AS runtime
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
# No shell, no package manager
USER nonroot:nonroot
# Read-only root filesystem set via securityContext in Kubernetes
# Sign image after push (in CI)
cosign sign --key cosign.key myorg/my-app:${{ github.sha }}
# Verify image signature before deployment
cosign verify --key cosign.pub myorg/my-app:latest
# Kyverno policy — enforce image signatures
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: enforce
rules:
- name: verify-signature
match:
resources:
kinds: [Pod]
verifyImages:
- imageReferences: ["myorg/*"]
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
<your-cosign-public-key>
-----END PUBLIC KEY-----
┌─────────────────────────────────────────────────────────────────────┐
│ IDE / Local │
│ • Semgrep IDE plugin (VSCode, IntelliJ) │
│ • gitleaks protect --staged (pre-commit hook) │
└──────────────────────────────┬──────────────────────────────────────┘
│ git push
┌──────────────────────────────▼──────────────────────────────────────┐
│ PR Gate (< 5 min, blocks merge on CRITICAL) │
│ • Semgrep --config=auto │
│ • Gitleaks detect │
│ • Trivy fs . --severity CRITICAL │
│ • ZAP Baseline Scan (passive, non-destructive) │
│ • Conftest / OPA against changed manifests │
└──────────────────────────────┬──────────────────────────────────────┘
│ merge to main
┌──────────────────────────────▼──────────────────────────────────────┐
│ Image Build Gate (< 10 min, blocks push on CRITICAL) │
│ • Trivy image scan │
│ • cosign sign │
│ • SBOM generation (trivy --format spdx-json) │
└──────────────────────────────┬──────────────────────────────────────┘
│ pre-release
┌──────────────────────────────▼──────────────────────────────────────┐
│ Pre-Release Gate (< 30 min, manual approval gate) │
│ • ZAP Full Scan (test environment) │
│ • Nuclei CVE scan │
│ • Dependency license compliance check │
│ • DefectDojo / Security Hub findings review │
└─────────────────────────────────────────────────────────────────────┘
Centralize all findings in DefectDojo or AWS Security Hub:
# Import Trivy SARIF to DefectDojo
curl -X POST https://defectdojo.myorg.com/api/v2/import-scan/ \
-H "Authorization: Token $DEFECTDOJO_TOKEN" \
-F "scan_type=SARIF" \
-F "file=@trivy-results.sarif" \
-F "engagement=1" \
-F "product=my-app" \
-F "minimum_severity=High"
| Level | What's Automated |
|---|---|
| Level 0 | No security automation |
| Level 1 | Gitleaks pre-commit + npm audit in CI |
| Level 2 | Semgrep + Trivy in PR gate, blocks on CRITICAL |
| Level 3 | ZAP DAST + Policy-as-Code (OPA/Kyverno) + Falco runtime |
| Level 4 | Full pipeline with signing, SBOM, centralized findings dashboard |