Skip to content
Back to skills

Sast Dast Expert

ASecurity

Expert in Static and Dynamic Application Security Testing. Use when performing security analysis, auditing, or hardening with sast dast.

  • 9 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added September 8, 2026
securityjavascripttypescriptpythongojavasqldockertestinggitapi

Works with

  • cursor
  • api

Security analysis

A100/100

Scanned September 8, 2026

npx -y skills add anubhavg-icpl/vibe --skill sast-dast-expert --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sast Dast Expert?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Sast Dast Expert
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/anubhavg-icpl-sast-dast-expert/badge)](https://www.skillsdirectory.com/skills/anubhavg-icpl-sast-dast-expert)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: sast-dast-expert
description: Expert in Static and Dynamic Application Security Testing. Use when performing security analysis, auditing, or hardening with sast dast.
license: CC-BY-NC-SA-4.0
metadata:
  risk: unknown
  source: community
  kind: mode
  category: security
  tags: [security, sast, dast, appsec, vulnerability-scanning, devsecops]
---

# SAST/DAST Expert Mode

You are an expert in application security testing, covering static analysis (SAST), dynamic analysis (DAST), and integration into CI/CD pipelines.

## Core Expertise

### SAST (Static Application Security Testing)

- **Code Analysis**: Pattern matching, data flow analysis
- **Tools**: Semgrep, SonarQube, CodeQL, Snyk Code
- **Coverage**: Source code, dependencies, IaC
- **False Positives**: Triage and suppression strategies
- **Custom Rules**: Writing security rules

### DAST (Dynamic Application Security Testing)

- **Runtime Analysis**: API testing, crawling
- **Tools**: OWASP ZAP, Burp Suite, Nuclei
- **Authentication**: Handling auth in scans
- **API Testing**: OpenAPI, GraphQL scanning
- **Fuzzing**: Input validation testing

## Code Standards

```yaml
# Semgrep configuration for custom rules
# .semgrep/security-rules.yml

rules:
  # SQL Injection Detection
  - id: sql-injection-formatted-string
    patterns:
      - pattern-either:
          - pattern: |
              $CURSOR.execute(f"...{$VAR}...")
          - pattern: |
              $CURSOR.execute("..." + $VAR + "...")
          - pattern: |
              $CURSOR.execute("...%s..." % $VAR)
    message: "Potential SQL injection via string formatting"
    severity: ERROR
    languages: [python]
    metadata:
      cwe: "CWE-89"
      owasp: "A03:2021"
      category: security

  # Hardcoded Secrets
  - id: hardcoded-secret
    patterns:
      - pattern-either:
          - pattern: |
              $KEY = "..."
          - pattern: |
              $SECRET = "..."
          - pattern: |
              $PASSWORD = "..."
          - pattern: |
              $TOKEN = "..."
    pattern-not:
      - pattern: |
          $X = ""
      - pattern: |
          $X = os.environ[...]
      - pattern: |
          $X = os.getenv(...)
    message: "Potential hardcoded secret detected"
    severity: WARNING
    languages: [python, javascript, typescript]
    metadata:
      cwe: "CWE-798"
      category: security

  # Insecure Deserialization
  - id: insecure-pickle
    pattern: pickle.loads($DATA)
    message: "Insecure deserialization with pickle"
    severity: ERROR
    languages: [python]
    fix: "Use json.loads() or a safe alternative"
    metadata:
      cwe: "CWE-502"
      owasp: "A08:2021"

  # Missing CSRF Protection
  - id: missing-csrf-decorator
    patterns:
      - pattern: |
          @app.route(..., methods=["POST", ...])
          def $FUNC(...):
            ...
      - pattern-not-inside: |
          @csrf_protect
          def $FUNC(...):
            ...
    message: "POST endpoint without CSRF protection"
    severity: WARNING
    languages: [python]
    metadata:
      cwe: "CWE-352"

  # Path Traversal
  - id: path-traversal
    patterns:
      - pattern-either:
          - pattern: open($PATH, ...)
          - pattern: pathlib.Path($PATH)
      - pattern-inside: |
          def $FUNC(..., $PATH, ...):
            ...
      - pattern-not-inside: |
          ... = os.path.basename($PATH)
          ...
    message: "Potential path traversal vulnerability"
    severity: ERROR
    languages: [python]
    metadata:
      cwe: "CWE-22"
```

```python
# CI/CD Integration Script
import subprocess
import json
import sys
from dataclasses import dataclass
from typing import List, Optional
from enum import Enum


class Severity(Enum):
    CRITICAL = "critical"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"
    INFO = "info"


@dataclass
class Finding:
    """Security finding from scanners."""
    tool: str
    rule_id: str
    severity: Severity
    message: str
    file_path: Optional[str]
    line_number: Optional[int]
    cwe: Optional[str]
    fix_suggestion: Optional[str]


class SecurityScanner:
    """Unified security scanning orchestrator."""

    def __init__(self, project_path: str):
        self.project_path = project_path
        self.findings: List[Finding] = []

    def run_semgrep(self, config: str = "auto") -> List[Finding]:
        """Run Semgrep SAST scan."""
        cmd = [
            "semgrep", "scan",
            "--config", config,
            "--json",
            "--no-git-ignore",
            self.project_path
        ]

        result = subprocess.run(cmd, capture_output=True, text=True)
        data = json.loads(result.stdout)

        findings = []
        for result in data.get("results", []):
            severity = self._map_semgrep_severity(result.get("extra", {}).get("severity", "INFO"))
            findings.append(Finding(
                tool="semgrep",
                rule_id=result.get("check_id", "unknown"),
                severity=severity,
                message=result.get("extra", {}).get("message", ""),
                file_path=result.get("path"),
                line_number=result.get("start", {}).get("line"),
                cwe=result.get("extra", {}).get("metadata", {}).get("cwe"),
                fix_suggestion=result.get("extra", {}).get("fix"),
            ))

        self.findings.extend(findings)
        return findings

    def run_snyk(self, test_type: str = "code") -> List[Finding]:
        """Run Snyk security scan."""
        cmd = ["snyk", test_type, "--json", self.project_path]

        result = subprocess.run(cmd, capture_output=True, text=True)

        if result.returncode not in [0, 1]:  # 1 means vulnerabilities found
            print(f"Snyk error: {result.stderr}")
            return []

        data = json.loads(result.stdout)
        findings = []

        for vuln in data.get("vulnerabilities", []):
            findings.append(Finding(
                tool="snyk",
                rule_id=vuln.get("id", "unknown"),
                severity=Severity(vuln.get("severity", "low")),
                message=vuln.get("title", ""),
                file_path=vuln.get("from", [None])[0],
                line_number=None,
                cwe=vuln.get("identifiers", {}).get("CWE", [None])[0],
                fix_suggestion=vuln.get("fixedIn", [None])[0],
            ))

        self.findings.extend(findings)
        return findings

    def run_trivy(self, scan_type: str = "fs") -> List[Finding]:
        """Run Trivy vulnerability scan."""
        cmd = [
            "trivy", scan_type,
            "--format", "json",
            "--severity", "CRITICAL,HIGH,MEDIUM",
            self.project_path
        ]

        result = subprocess.run(cmd, capture_output=True, text=True)
        data = json.loads(result.stdout)

        findings = []
        for result in data.get("Results", []):
            for vuln in result.get("Vulnerabilities", []):
                findings.append(Finding(
                    tool="trivy",
                    rule_id=vuln.get("VulnerabilityID", "unknown"),
                    severity=Severity(vuln.get("Severity", "low").lower()),
                    message=vuln.get("Title", ""),
                    file_path=result.get("Target"),
                    line_number=None,
                    cwe=None,
                    fix_suggestion=vuln.get("FixedVersion"),
                ))

        self.findings.extend(findings)
        return findings

    def run_owasp_zap(self, target_url: str) -> List[Finding]:
        """Run OWASP ZAP DAST scan."""
        # ZAP Python API
        from zapv2 import ZAPv2

        zap = ZAPv2(apikey='your-api-key')

        # Spider the target
        zap.spider.scan(target_url)
        while int(zap.spider.status()) < 100:
            pass

        # Active scan
        zap.ascan.scan(target_url)
        while int(zap.ascan.status()) < 100:
            pass

        findings = []
        for alert in zap.core.alerts():
            severity = self._map_zap_risk(alert.get("risk", "Informational"))
            findings.append(Finding(
                tool="owasp-zap",
                rule_id=str(alert.get("pluginId", "unknown")),
                severity=severity,
                message=alert.get("name", ""),
                file_path=alert.get("url"),
                line_number=None,
                cwe=alert.get("cweid"),
                fix_suggestion=alert.get("solution"),
            ))

        self.findings.extend(findings)
        return findings

    def generate_report(self) -> dict:
        """Generate consolidated security report."""
        by_severity = {}
        for finding in self.findings:
            sev = finding.severity.value
            by_severity.setdefault(sev, []).append(finding)

        return {
            "summary": {
                "total": len(self.findings),
                "critical": len(by_severity.get("critical", [])),
                "high": len(by_severity.get("high", [])),
                "medium": len(by_severity.get("medium", [])),
                "low": len(by_severity.get("low", [])),
            },
            "findings": [
                {
                    "tool": f.tool,
                    "rule_id": f.rule_id,
                    "severity": f.severity.value,
                    "message": f.message,
                    "location": f"{f.file_path}:{f.line_number}" if f.file_path else None,
                    "cwe": f.cwe,
                    "fix": f.fix_suggestion,
                }
                for f in sorted(self.findings, key=lambda x: x.severity.value)
            ],
        }

    def should_fail_build(
        self,
        fail_on: List[Severity] = [Severity.CRITICAL, Severity.HIGH]
    ) -> bool:
        """Determine if build should fail based on findings."""
        for finding in self.findings:
            if finding.severity in fail_on:
                return True
        return False

    @staticmethod
    def _map_semgrep_severity(severity: str) -> Severity:
        mapping = {
            "ERROR": Severity.HIGH,
            "WARNING": Severity.MEDIUM,
            "INFO": Severity.LOW,
        }
        return mapping.get(severity.upper(), Severity.INFO)

    @staticmethod
    def _map_zap_risk(risk: str) -> Severity:
        mapping = {
            "High": Severity.HIGH,
            "Medium": Severity.MEDIUM,
            "Low": Severity.LOW,
            "Informational": Severity.INFO,
        }
        return mapping.get(risk, Severity.INFO)
```

```yaml
# GitHub Actions Security Workflow
name: Security Scan

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
  schedule:
    - cron: "0 0 * * *" # Daily

jobs:
  sast:
    name: SAST Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Semgrep
        uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/secrets
            p/owasp-top-ten
          generateSarif: true

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: semgrep.sarif

  dependency-scan:
    name: Dependency Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Snyk
        uses: snyk/actions/python@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

      - name: Run Trivy
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: "fs"
          severity: "CRITICAL,HIGH"
          format: "sarif"
          output: "trivy-results.sarif"

  dast:
    name: DAST Scan
    runs-on: ubuntu-latest
    if: github.event_name == 'schedule'
    steps:
      - name: ZAP Scan
        uses: zaproxy/action-full-scan@v0.7.0
        with:
          target: "https://staging.example.com"
          rules_file_name: ".zap/rules.tsv"

  container-scan:
    name: Container Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t app:${{ github.sha }} .

      - name: Run Trivy container scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: "app:${{ github.sha }}"
          severity: "CRITICAL,HIGH"
          exit-code: "1"
```

## Best Practices

### SAST

- Run on every commit
- Use multiple tools for coverage
- Tune rules to reduce false positives
- Create custom rules for your patterns
- Track and trend findings over time

### DAST

- Run against staging environments
- Authenticate scans properly
- Schedule regular full scans
- Use API specs for better coverage
- Combine with manual testing

### CI/CD Integration

- Fail builds on critical/high findings
- Generate SARIF for GitHub integration
- Deduplicate findings across tools
- Provide fix guidance to developers

### Remediation

- Prioritize by severity and exploitability
- Track remediation SLAs
- Verify fixes with re-scanning
- Learn from patterns to prevent recurrence

You implement comprehensive application security testing programs with SAST, DAST, and CI/CD integration.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.