How to Catch Security Vulnerabilities Before They Reach Your

How to Catch Security Vulnerabilities Before They Reach Your Pull Requests


Author: Umair Mirza | Date: September 14, 2026 | Tag: #Security


!How to Catch Security Vulnerabilities in Code Before They Reach Your Pull Requests


Security reviews are most effective when developers receive feedback while the code is still fresh in their minds. Waiting until a pull request, CI build, or penetration test to find exposed credentials and insecure patterns creates unnecessary rework.


A lightweight way to shift security left is to run static application security testing (SAST) locally through Git pre-commit hooks.


In this guide, you'll install the DevSkim CLI, wire it into pre-commit so it lints staged files, add a dedicated secret scanner alongside it, verify the setup with a deliberate failure, and enforce the same checks in CI.


What We'll Cover:



Why Pre-Commit Security Scanning?


By 2026, supply chain attacks and credential leaks remain among the most common causes of breaches. The average cost of a data breach now exceeds $5 million, and organizations are under increasing pressure to demonstrate secure development practices.


Shifting security left is no longer a nice-to-have โ€” it's a regulatory and business imperative. Pre-commit hooks catch issues at the earliest possible stage, before code ever leaves a developer's machine. This approach offers several advantages:


  • Immediate feedback while context is fresh
  • Reduced rework by catching issues before code review
  • Lower CI costs by preventing bad commits from triggering expensive pipelines
  • Consistent enforcement across the entire team

What Is DevSkim?


DevSkim is an open-source, lightweight security linter from Microsoft. Unlike heavier SAST tools, DevSkim is designed for speed and developer experience โ€” it scans code in milliseconds and provides actionable, context-aware warnings for insecure patterns.


DevSkim supports dozens of languages including Python, JavaScript, TypeScript, Go, Java, C#, and more. It comes with a rich rule set covering common vulnerabilities like SQL injection, weak cryptography, insecure deserialization, and hardcoded secrets.


In 2026, DevSkim has become a popular choice for pre-commit workflows precisely because it balances coverage with speed โ€” a critical requirement when hooks run on every commit.


Prerequisites


Before you begin, ensure you have:


  • Git installed and a repository to work with
  • Python 3.9+ (for the pre-commit framework)
  • pip or pipx for installing tools
  • Docker (optional, for containerized scanning)

Create a Pre-Commit Configuration


The pre-commit framework makes it easy to manage and share Git hooks across a team. If you don't already have it installed:


pip install pre-commit

Next, create a .pre-commit-config.yaml file at the root of your repository:


repos:
  - repo: https://github.com/microsoft/DevSkim
    rev: v1.0.50
    hooks:
      - id: devskim
        name: DevSkim Security Linter
        entry: devskim analyze
        language: system
        types: [text]
        pass_filenames: true
        args: ["--file-format", "sarif", "--output", "devskim-results.sarif"]

  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.21.0
    hooks:
      - id: gitleaks
        name: Gitleaks Secret Scanner

This configuration does two things:


  1. DevSkim scans staged files for insecure patterns
  2. Gitleaks scans for hardcoded secrets, API keys, and credentials

  3. Install the Git Hook


    Run the following command in your repository root:


    pre-commit install
    

    This installs the hook into .git/hooks/pre-commit. From now on, every git commit will trigger the configured scanners.


    You can also run the hooks manually against all files:


    pre-commit run --all-files
    

    Verify the Setup With a Deliberate Failure


    To confirm the hook works, create a file with a known insecure pattern:


    # insecure_test.py
    import hashlib
    
    password = "admin123"  # hardcoded credential
    hashed = hashlib.md5(password.encode()).hexdigest()
    

    Now stage and commit the file:


    git add insecure_test.py
    git commit -m "test security hook"
    

    DevSkim should flag the weak MD5 usage, and Gitleaks should flag the hardcoded password. The commit will be blocked โ€” that's exactly what you want.


    Example: Catching a Hardcoded Secret


    Here's the kind of output Gitleaks produces when it catches an AWS key:


    Finding:     AWS Access Key
    Secret:      AKIAIOSFODNN7EXAMPLE
    RuleID:      aws-access-token
    Entropy:     3.65
    File:        config.py
    Line:        14
    

    Because the hook runs locally, the secret never reaches the remote repository. This is critical โ€” once a secret is pushed, it must be considered compromised and rotated immediately.


    Keep Hooks Fast and Focused


    Pre-commit hooks should run in under a few seconds. If they slow down commits, developers will bypass them with --no-verify. To keep things fast:


    • Limit scope โ€” scan only staged files, not the entire repo
    • Use lightweight tools โ€” DevSkim and Gitleaks are optimized for speed
    • Avoid duplicate scans โ€” don't run the same check in pre-commit and pre-push
    • Parallelize โ€” pre-commit runs hooks concurrently by default

    Handling False Positives


    No scanner is perfect. When DevSkim or Gitleaks flags a false positive, use inline suppression comments:


    # devskim:ignore DS126858
    hashlib.md5(password.encode())
    

    For Gitleaks, use a .gitleaks.toml config file to define allowlists:


    [allowlist]
    description = "Ignore test fixtures"
    paths = ["tests/fixtures/.*"]
    

    Document every suppression with a comment explaining why it's safe. Undocumented suppressions tend to multiply and erode security posture over time.


    Add Security Checks to CI Too


    Pre-commit hooks are a first line of defense, but they can be bypassed. Enforce the same checks in CI to guarantee coverage:


    # .github/workflows/security.yml
    name: Security Scan
    on: [push, pull_request]
    
    jobs:
      scan:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-python@v5
            with:
              python-version: '3.12'
          - run: pip install pre-commit
          - run: pre-commit run --all-files
    

    This ensures that even if a developer skips the local hook, the CI will catch the issue before merge. By 2026, most CI platforms also offer native secret scanning (GitHub Advanced Security, GitLab Secret Detection), which can complement the setup.


    Practical Rollout Tips


    • Pilot with a small team โ€” get feedback before mandating across the org
    • Pre-stage the config โ€” add .pre-commit-config.yaml and .gitleaks.toml to the repo template
    • Communicate clearly โ€” explain why the hooks exist and how to respond to alerts
    • Measure impact โ€” track how many issues are caught pre-commit vs. in CI or production
    • Review rules quarterly โ€” the threat landscape changes; keep rules current

    Final Thoughts


    Catching security vulnerabilities before they reach a pull request is one of the highest-leverage investments a development team can make. Pre-commit hooks powered by DevSkim and Gitleaks deliver fast, actionable feedback at the exact moment developers can act on it.


    Combined with CI enforcement and periodic rule reviews, this lightweight shift-left approach meaningfully reduces the risk of shipping insecure code โ€” without slowing down delivery.




    Have you integrated security scanning into your pre-commit workflow? Share your experience in the comments.

    via FreeCodeCamp

Related