We all agree that you have to secure your code. The hard part is knowing where to start. Here I present SAST and SCA implementations for your JavaScript and TypeScript repositories — open-source tools you can wire up yourself in your CI/CD pipeline or pre-commit hooks.
See also: Security Post-it #7 – Software Security Testing for Golang.
What are SAST and SCA?
Static Application Security Testing (SAST) scans the code you write for security vulnerabilities. Software Composition Analysis (SCA) scans your dependencies for known vulnerabilities.
Both are necessary for an effective security approach. SAST should run both synchronously (blocking CI/CD to prevent insecure code merges) and asynchronously (alerting the security team in real time). SCA must be asynchronous — running only on push misses vulnerable dependencies in dormant repositories. Dead repositories are full of vulnerable dependencies. Run it continuously and consider Renovabot to auto-create fix PRs.
SAST — semgrep / njsscan
For effective JS/TS security coverage, use semgrep. I also recommend njsscan, which wraps semgrep with additional rules focused on server-side JavaScript. For client-side coverage (DOM-XSS, postMessage abuse, open redirects), the extended semgrep rules below are useful.
Install
# Semgrep $ pip install semgrep # Njsscan $ pip install njsscanAudit with semgrep
Paranoid mode
# OWASP Top Ten + extended client-side rules $ semgrep \ --config=r/javascript.browser.security.insufficient-postmessage-origin-validation.insufficient-postmessage-origin-validation \ --config=r/javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization \ --config=r/javascript.browser.security.dom-based-xss.dom-based-xss \ --config=r/typescript.react.security.audit.react-css-injection.react-css-injection \ --config=r/typescript.react.security.audit.react-href-var.react-href-var \ --config=p/owasp-top-ten \ __CODE_DIRECTORY__CI-safe mode (low false positives)
$ semgrep --config=p/ci __CODE_DIRECTORY__JSON output
$ semgrep --config=p/ci __CODE_DIRECTORY__ -o /tmp/semgrep.json --json $ cat /tmp/semgrep.json | jq .resultsAudit with njsscan
$ njsscan __CODE_DIRECTORY__ $ njsscan __CODE_DIRECTORY__ -o /tmp/njsscan.json --json $ cat /tmp/njsscan.json | jq .nodejs $ cat /tmp/njsscan.json | jq .templatesExample — OWASP Juice Shop
Let's use OWASP Juice Shop — "probably the most modern and sophisticated insecure web application".
$ git clone https://github.com/juice-shop/juice-shop /tmp/juice-shop $ semgrep \ --config=r/javascript.browser.security.insufficient-postmessage-origin-validation.insufficient-postmessage-origin-validation \ --config=r/javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization \ --config=r/javascript.browser.security.dom-based-xss.dom-based-xss \ --config=r/typescript.react.security.audit.react-css-injection.react-css-injection \ --config=r/typescript.react.security.audit.react-href-var.react-href-var \ --config=p/owasp-top-ten \ /tmp/juice-shop/ … /tmp/juice-shop/data/static/codefixes/unionSqlInjectionChallenge_3.ts javascript.express.security.injection.tainted-sql-string.tainted-sql-string Detected user input used to manually construct a SQL string. This is usually bad practice because manual construction could accidentally result in a SQL injection. Use a parameterized query or an ORM such as Sequelize instead. Details: https://sg.run/66ZL 10┆ ... criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) ... Ran 471 rules on 979 files: 41 findings.CI Integration
Semgrep documentation: Running Semgrep CI without Semgrep App — supports GitHub Actions, GitLab CI/CD, Jenkins, BitBucket Pipelines, CircleCI, Buildkite.
SCA — depscan
Depscan by AppThreat is a fully open-source security audit for project dependencies based on known vulnerabilities and advisories. cdxgen extracts all dependencies from package-lock.json, yarn.lock, pnpm-lock.yaml, and more — including transitive dependencies.
Install
# Install cdxgen (use -g for global install instead of --prefix /tmp/) $ npm install --prefix /tmp/ @appthreat/cdxgen $ PATH=$PATH:/tmp/node_modules/.bin $ pip install appthreat-depscanAudit
$ cdxgen -o /tmp/bom.json __CODE_DIRECTORY__ $ depscan --bom /tmp/bom.json -o /tmp/depscan.json $ cat /tmp/depscan.json | jq .Example
$ git clone https://github.com/Faten4/HW-Search /tmp/HW-Search $ cdxgen -o /tmp/bom.json /tmp/HW-Search/ $ depscan --bom /tmp/bom.json -o /tmp/depscan.json Dependency Scan Results (nodejs) ╔════════════════╤═══════════╤═══════════════════════╤═════════╤═════════════╤══════════╤═══════╗ ║ Id │ Package │ Insights │ Version │ Fix Version │ Severity │ Score ║ ╟────────────────┼───────────┼───────────────────────┼─────────┼─────────────┼──────────┼───────╢ ║ CVE-2021-3803 │ nth-check │ ℹ Indirect dependency │ <2.0.1 │ 2.0.1 │ HIGH │ 7.5 ║ ╟────────────────┼───────────┼───────────────────────┼─────────┼─────────────┼──────────┼───────╢ ║ CVE-2022-40215 │ tabs │ 🎯 Direct usage │ <=3.7.1 │ │ MEDIUM │ 5.4 ║ ╟────────────────┼───────────┼───────────────────────┼─────────┼─────────────┼──────────┼───────╢ ║ CVE-2022-33154 │ schema │ ℹ Indirect dependency │ <1.13.1 │ 1.13.1 │ MEDIUM │ 5.4 ║ ╚════════════════╧═══════════╧═══════════════════════╧═════════╧═════════════╧══════════╧═══════╝CI Integration
Depscan documentation: Integration with CI environments — supports GitHub Actions. Also see the ShiftLeft project.
Conclusion
You don't need an expensive scanner like Snyk or CheckMarx. With semgrep and depscan wired into your pre-commit hooks, CI/CD, and as async jobs, you'll have a complete view of your application security posture and developers will build security awareness naturally.
At Tandem Technology, we help you improve your development practices during a workshop to harden your code repositories.