Understanding SAST
What Is SAST in Simple Terms
SAST is a security reviewer that reads your code automatically. Instead of waiting for a penetration test or a security audit, SAST runs on every pull request and flags potential vulnerabilities before the code is merged. SQL injection risks, hardcoded passwords, insecure cryptography, path traversal bugs -- SAST catches these at the earliest and cheapest point in the development lifecycle.
At Razorpay, every pull request is scanned by Semgrep before it can be merged. Engineers see security feedback alongside test results -- in the same PR, at the same time.
How It Works
+------------------------------------------+| Source code (PR or commit) |+------------------------------------------+ | v+------------------------------------------+| SAST Tool parses code || Builds AST (Abstract Syntax Tree) || No code execution needed |+------------------------------------------+ | v+------------------------------------------+| Matches patterns against rule sets || Rule: user input reaches SQL query? || Rule: private key in string literal? || Rule: MD5 used for password hashing? |+------------------------------------------+ | v+------------------------------------------+| Findings with severity: INFO/WARN/ERROR || File, line number, explanation || Pass/fail based on severity threshold |+------------------------------------------+SAST in GitHub Actions with Semgrep:
sast-scan: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - name: Run Semgrep SAST uses: semgrep/semgrep-action@v1 with: ## Pre-built rulesets for common vulnerability classes config: > p/nodejs p/secrets p/sql-injection p/xss p/owasp-top-ten ## Generate SARIF for GitHub Security tab generateSarif: true - name: Upload SARIF to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 if: always() with: sarif_file: semgrep.sarif ## CodeQL for deeper analysis (GitHub native) codeql: runs-on: ubuntu-latest permissions: security-events: write steps: - uses: actions/checkout@v4 - uses: github/codeql-action/init@v3 with: languages: javascript - uses: github/codeql-action/autobuild@v3 - uses: github/codeql-action/analyze@v3Semgrep custom rules:
## .semgrep/custom-rules.yaml## Block patterns specific to your codebaserules: ## Catch direct database queries without parameterisation - id: unsafe-query-construction pattern: | db.query("..." + $INPUT) message: | Direct string concatenation in SQL query. Use parameterised queries: db.query(sql, [params]) severity: ERROR languages: [javascript] ## Catch console.log of potentially sensitive objects - id: log-sensitive-data pattern: console.log($REQ.body) message: Logging request body may expose passwords or tokens. severity: WARNING languages: [javascript]Practical Commands
## Install Semgreppip install semgrep ## Run locally before committingsemgrep --config=p/nodejs src/semgrep --config=p/secrets . ## Run with specific rule filesemgrep --config=.semgrep/custom-rules.yaml src/ ## Output JSON for processingsemgrep --config=p/owasp-top-ten --json src/ | \ jq '.results[] | {file: .path, line: .start.line, message: .extra.message}' ## SonarQube scan (if using SonarQube)sonar-scanner \ -Dsonar.projectKey=payment-api \ -Dsonar.sources=src/ \ -Dsonar.host.url=https://sonar.internal \ -Dsonar.token=$SONAR_TOKENTroubleshooting
| Symptom | Check | What to Look For |
|---|---|---|
| Too many false positives | Review rules used | Disable overly broad rules |
| SAST blocking on old code | Baseline file | Semgrep supports baseline to ignore existing findings |
| Scan too slow | Rule count | Use targeted rulesets, not p/all |
PLACEMENT PRO TIP**Tip:** Start SAST with `p/secrets` ruleset only. Secret detection has very low false positive rates and catches real critical issues -- API keys, passwords, private keys accidentally committed. Once the team is comfortable with SAST blocking pipelines, gradually add broader rulesets like `p/owasp-top-ten`.
REMEMBER THIS**Remember:** SAST finds potential vulnerabilities in code -- it does not prove they are exploitable. A SQL injection finding still needs to be reviewed to confirm the input actually reaches the database without sanitisation. SAST is a signal, not a verdict. Triage findings by severity and context.
COMMON MISTAKE / WARNING**Security:** Configure SAST to block only on HIGH and CRITICAL findings. Blocking on MEDIUM and LOW creates noise that causes teams to ignore the scanner entirely. A blocked pipeline with genuine HIGH findings gets fixed. A pipeline blocked every day on INFO findings gets `continue-on-error: true` added and never gets fixed.
COMMON MISTAKE / WARNING**Common Mistake:** Running SAST as a reporting-only step that never blocks the pipeline. If SAST findings do not block merges, engineers stop reading them within a week. SAST must be a gate -- HIGH and CRITICAL findings block the PR. This is the only way to ensure findings get fixed rather than accumulated.