Hardening it requires three layers — SAST (what your code does), SCA (what your code depends on), and secret scanning (what your code accidentally commits). The trick is layering them without generating a firehose of alerts that developers learn to ignore.​‌‌​​‌​​‍​‌‌​​‌​‌‍​‌‌‌​‌‌​‍​‌‌‌​​‌‌‍​‌‌​​‌​‌‍​‌‌​​​‌‌‍​‌‌​‌‌‌‌‍​‌‌‌​​​​‍​‌‌‌​​‌‌‍​​‌​‌‌​‌‍​‌‌‌​​​​‍​‌‌​‌​​‌‍​‌‌‌​​​​‍​‌‌​​‌​‌‍​‌‌​‌‌​​‍​‌‌​‌​​‌‍​‌‌​‌‌‌​‍​‌‌​​‌​‌‍​​‌​‌‌​‌‍​‌‌​‌​​​‍​‌‌​​​​‌‍​‌‌‌​​‌​‍​‌‌​​‌​​‍​‌‌​​‌​‌‍​‌‌​‌‌‌​‍​‌‌​‌​​‌‍​‌‌​‌‌‌​‍​‌‌​​‌‌‌‍​​‌​‌‌​‌‍​‌‌‌​​‌‌‍​‌‌​​​​‌‍​‌‌‌​​‌‌‍​‌‌‌​‌​​‍​​‌​‌‌​‌‍​‌‌‌​​‌‌‍​‌‌​​​‌‌‍​‌‌​​​​‌‍​​‌​‌‌​‌‍​‌‌‌​​‌‌‍​‌‌​​‌​‌‍​‌‌​​​‌‌‍​‌‌‌​​‌​‍​‌‌​​‌​‌‍​‌‌‌​‌​​‍​‌‌‌​​‌‌

Layer 1: SAST — Catch Bugs Before They Become Breaches

Static Application Security Testing analyses source code for security vulnerabilities without executing it. For SMBs, two tools dominate:

Semgrep — open-source, fast, and community-maintained with pre-built rule packs. Ideal for teams wanting immediate value without tuning.​‌‌​​‌​​‍​‌‌​​‌​‌‍​‌‌‌​‌‌​‍​‌‌‌​​‌‌‍​‌‌​​‌​‌‍​‌‌​​​‌‌‍​‌‌​‌‌‌‌‍​‌‌‌​​​​‍​‌‌‌​​‌‌‍​​‌​‌‌​‌‍​‌‌‌​​​​‍​‌‌​‌​​‌‍​‌‌‌​​​​‍​‌‌​​‌​‌‍​‌‌​‌‌​​‍​‌‌​‌​​‌‍​‌‌​‌‌‌​‍​‌‌​​‌​‌‍​​‌​‌‌​‌‍​‌‌​‌​​​‍​‌‌​​​​‌‍​‌‌‌​​‌​‍​‌‌​​‌​​‍​‌‌​​‌​‌‍​‌‌​‌‌‌​‍​‌‌​‌​​‌‍​‌‌​‌‌‌​‍​‌‌​​‌‌‌‍​​‌​‌‌​‌‍​‌‌‌​​‌‌‍​‌‌​​​​‌‍​‌‌‌​​‌‌‍​‌‌‌​‌​​‍​​‌​‌‌​‌‍​‌‌‌​​‌‌‍​‌‌​​​‌‌‍​‌‌​​​​‌‍​​‌​‌‌​‌‍​‌‌‌​​‌‌‍​‌‌​​‌​‌‍​‌‌​​​‌‌‍​‌‌‌​​‌​‍​‌‌​​‌​‌‍​‌‌‌​‌​​‍​‌‌‌​​‌‌

CodeQL — GitHub's engine powering Dependabot security alerts. Deeper analysis, but heavier on CI minutes.

GitHub Actions: Semgrep (Advisory-Only)

name: Semgrep SAST
on: [pull_request]
jobs:
  semgrep:
    runs-on: ubuntu-latest
    container:
      image: semgrep/semgrep
    steps:
      - uses: actions/checkout@v4
      - name: Run Semgrep
        continue-on-error: true  # Advisory-only — does not block merge
        run: |
          semgrep ci --config=auto --sarif --output=semgrep.sarif \
            --metrics=off
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: semgrep.sarif

When to fail the build: Switch continue-on-error: true to false once you have a 14-day clean run with zero false positives. Enable blocking only for severity: ERROR and confidence: HIGH initially.

GitLab CI: CodeQL Blocking (Hardened Mode)

codeql-sast:
  stage: test
  image: mcr.microsoft.com/cstsectools/codeql-container:latest
  script:
    - codeql database create codeql-db --language=javascript,python
    - codeql database analyze codeql-db --format=sarif-latest \
        --output=codeql-results.sarif \
        javascript-code-scanning.qls
    - |
      if grep -q '"ruleId"' codeql-results.sarif; then
        echo "FATAL: CodeQL findings detected. Fix before merge."
        exit 1
      fi
  allow_failure: false  # Blocks merge on any finding

Layer 2: SCA — Know What You're Pulling In

Software Composition Analysis scans dependencies for known vulnerabilities. After the Axios RAT (March 2026, 100M+ weekly downloads) and Chalk/Debug wallet drainer (2.6B+ combined downloads compromised) [3], this layer is non-negotiable.

Trivy — Aqua Security's scanner. Fast, single-binary, covers both containers and package manifests.

OSV-Scanner — Google's open-source vulnerability scanner. Queries the OSV database directly — no vendor lock-in.

GitHub Actions: Trivy SCA + Fail on Critical

name: Trivy SCA
on:
  pull_request:
  schedule:
    - cron: '0 6 * * 1'  # Weekly full scan
jobs:
  trivy-sca:
 

   runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Scan dependencies
        run: |
          docker run --rm -v "$(pwd):/src" aquasec/trivy \
            fs /src \
            --scanners vuln \
            --severity CRITICAL,HIGH \
            --exit-code 1 \
            --ignore-unfixed \
            --format sarif \
            --output trivy-results.sarif
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: trivy-results.sarif

--exit-code 1 fails the build on CRITICAL or HIGH findings. --ignore-unfixed suppresses vulnerabilities with no upstream patch — critical for reducing noise.

Pro tip: Run SCA on a schedule as well as on PRs. The Chalk maintainer account was compromised and publishing malicious versions within 30 minutes of account takeover [3]. A weekly cron catches drift even if devs aren't actively committing.

Layer 3: Secret Scanning — Don't Ship Credentials

The CanisterSprawl worm specifically hunted npm publish tokens and used them to propagate across the registry [1]. Gitleaks detects 150+ credential patterns out of the box.

GitLab CI: Gitleaks (Pre-Commit + Pipeline)

# .pre-commit-config.yaml — runs locally before commit
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

# .gitlab-ci.yml — backstop in pipeline
gitleaks:
  stage: test
  image: zricethezav/gitleaks:latest
  script:
    - gitleaks detect --source=. --verbose --redact
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  allow_failure: false  # Always block

Secret scanning should ALWAYS fail the build. There is no advisory-only mode for a leaked AWS key. If Gitleaks fires, someone must rotate credentials immediately.

If You Use GitHub: Enable Push Protection

GitHub's native secret scanning (included with any paid plan from Team upward) blocks pushes containing detected secrets before they reach the remote:

# No YAML needed — enable in repo Settings → Security → Secret scanning
# Push protection blocks commits with detected credentials at git push time

This is the single highest-impact security control you can implement in under 60 seconds.

SLSA Level 1: Quick Wins for Every Pipeline

SLSA (Supply-chain Levels for Software Artifacts) is the framework for supply chain integrity. Level 1 requires build provenance — proof of where and how your software was built. The good news for SMBs: it is trivially achievable [2].

GitHub Actions: Generate Provenance

name: Build with Provenance
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build artifact
        run: |
          npm ci
          npm run build
          tar -czf dist.tar.gz dist/
      - uses: actions/attest-build-provenance@v2
        with:
          subject-path: dist.tar.gz

That is it. Three lines of YAML generates a cryptographically signed attestation linking the artifact to the exact commit and workflow that produced it.

Also consider for SLSA Level 1:

  • Pin actions to commit SHA: uses: actions/checkout@11bd719... instead of @v4
  • Require branch protection rules on main — no direct pushes, must use PRs
  • Enable workflow identity tokens for cloud deployments — no long-lived cloud secrets in CI

FAQ

Q: We are a five-person team. Is all this overkill?

No. The Chalk attack compromised a maintainer whose packages are downloaded 2.6 billion times weekly [3]. Small teams use the same dependencies as enterprises. Start with Gitleaks (free, 30 minutes to set up) and GitHub push protection. Add SAST and SCA incrementally.

Q: What is the difference between Trivy and Snyk for SCA?

Snyk provides a managed dashboard and prioritisation, but its free tier caps at 200 tests/month. Trivy is fully free, offline-capable, and scans containers alongside dependencies. For SMBs starting out, Trivy or OSV-Scanner avoids vendor lock-in while providing equivalent vulnerability coverage.

Q: Should we fail the build or just warn?

Secret scanning: always fail. SAST: start advisory-only for 14 days, tune out false positives, then fail on high/error. SCA: fail on critical immediately; fail on high after a clean baseline. The goal is signal, not noise.

Q: Does this slow down our CI pipeline?

Semgrep scans typical in 60-90 seconds. Trivy dependency scans in 30-45 seconds. Gitleaks in under 10 seconds. Run all three in parallel jobs — total pipeline time increase is typically under two minutes.

Conclusion

Supply chain attacks are no longer theoretical for Australian SMBs. They are automated, cross-ecosystem, and designed specifically to harvest CI/CD credentials. The three-layer approach — SAST, SCA, and secret scanning — catches vulnerabilities at every stage of the software lifecycle without requiring a dedicated AppSec team. Start with secret scanning (always block), add SCA with critical-level blocking, layer in SAST advisory-mode, and enable SLSA provenance. Each step takes under an hour and pays dividends every time a compromised package hits the registry.

Need help hardening your pipeline? Visit consult.lil.business for a free cybersecurity assessment tailored to Australian SMBs.

References

  1. No Off Season: Three Supply Chain Campaigns Hit npm, PyPI, and Docker Hub in 48 Hours — GitGuardian
  2. SLSA Specification Version 1.0 — slsa.dev
  3. Software Supply Chain Attacks 2025–2026: Axios, Shai-Hulud, Chalk — Cyber Army
  4. Chalk, Debug, and Color on npm Compromised — Semgrep Blog
  5. GitHub Actions: Generate Attestation Provenance — GitHub Docs
  6. CISA Known Exploited Vulnerabilities Catalog — Cybersecurity & Infrastructure Security Agency

Ready to strengthen your security?

Talk to lilMONSTER. We assess your risks, build the tools, and stay with you after the engagement ends. No clipboard-and-leave consulting.

Get a Free Consultation