There are two very different places bugs with security impact hide: in the open-source libraries you install, and in the code you write yourself. Beginners often only think about one of them. This guide covers both. You will learn to scan your dependencies for known, published vulnerabilities and to scan your own source code for risky patterns, using tools that are free to start with and simple to run.
What you will accomplish
You will end up with two lists: known vulnerabilities in the packages you depend on, and potential weaknesses in the code you wrote. Together those cover the large majority of what a beginner needs to worry about.
Prerequisites
- A code project you can run commands inside.
- A terminal and basic command-line comfort.
- Python installed (for one of the tools below) or Node.js, depending on your stack.
- The Safeguard CLI, installed in Step 1.
Step 1: Install the tools
First the dependency scanner:
curl -sSfL https://get.safeguard.sh/install.sh | sh
sg --version
Then a source-code scanner. Semgrep is a popular, free, open-source choice that finds risky patterns in the code you write:
python3 -m pip install semgrep
semgrep --version
Step 2: Find vulnerabilities in your dependencies
Most of your attack surface lives in code you did not write. Start there because it is the fastest win:
sg scan
This resolves every package your project pulls in, including transitive ones, and matches them against public vulnerability databases. You get a summary grouped by severity. These are known, documented issues with published fixes, so they are usually the easiest to resolve.
Step 3: Find weaknesses in your own code
Now scan the source you wrote. Semgrep ships with a curated rule set that catches common mistakes such as hardcoded secrets, SQL built from string concatenation, and unsafe deserialization:
semgrep --config auto .
The . means "scan this folder." Semgrep prints each match with the file, the line number, and an explanation of why it is risky.
Step 4: Read a finding and understand the risk
Pick one result and read it slowly. A dependency finding will tell you the CVE, the affected package, and the fixed version. A source-code finding will point at a specific line and describe the weakness class, for example "user input flows into a shell command."
Ask yourself one question for each: can untrusted input reach this code? A risky line that only ever handles hardcoded values is far less urgent than one on the path of a web request.
Step 5: Confirm a real issue with a quick check
For a dependency finding, ask the scanner to explain how the package got in:
sg scan finding CVE-2024-21538 --explain
For a source finding, open the file at the reported line and trace where the value comes from. If it originates from a request parameter, a form field, or a file upload, treat it as real and prioritize it.
Step 6: Search for leaked secrets
Secrets accidentally committed to a repository are one of the most common and most damaging findings. A fast check with git:
git log -p | grep -iE "api[_-]?key|secret|password|token" | head
This is a blunt instrument, but it surfaces obvious leaks quickly. Anything it finds should be rotated immediately, because rewriting history does not un-leak a key that was already pushed.
How to know it worked
- The dependency scan printed a findings summary with severities.
- Semgrep printed either matches with file and line numbers, or a clean "no findings" result.
- You were able to open at least one flagged line and explain, in a sentence, why it is risky.
If you can point at a specific finding and say what it is and whether input can reach it, the process worked. Finding zero issues is possible on a small project, but on anything sizable, expect a handful.
Next steps
- Fix the highest-severity dependency finding first, then re-scan to confirm it is gone.
- Address source findings that sit on untrusted-input paths before ones that do not.
- Automate both scans so they run on every change instead of only when you remember.
- Learn the weakness classes. Understanding categories like injection and taint flow makes source findings much faster to triage. The concepts library has short entries on each.
To understand how dependency scanning decides what is exploitable versus merely present, read about software composition analysis. If reviewing every source finding by hand feels overwhelming, Griffin AI can triage findings and draft fixes so you spend your time confirming rather than hunting. The guided path in the Safeguard Academy turns these one-off scans into a repeatable habit.
Frequently Asked Questions
What is the difference between scanning dependencies and scanning my own code? Dependency scanning, often called software composition analysis, matches the libraries you install against databases of known published vulnerabilities. Source-code scanning, often called static analysis, inspects the code you wrote for risky patterns. They find different problems, so a thorough beginner runs both.
Do I need to fix every finding I get? No. Fix by risk, not by count. A high-severity issue that untrusted input can reach matters far more than a low-severity one buried in code no external user can influence. Prioritizing is a normal and expected part of the work, not a shortcut.
Are free tools good enough to start? Yes. Free and open-source scanners like the ones in this guide are more than enough to find your first real vulnerabilities and build good habits. As your project grows you may want reachability analysis and automated fixes to cut down on noise, but that is an optimization, not a starting requirement.
What should I do if I find a leaked secret? Rotate it immediately, meaning generate a new credential and revoke the old one. Removing the secret from your code or rewriting git history is not enough on its own, because anyone who already pulled the repository still has the exposed value.
Want a single place to track both kinds of findings? Sign up at app.safeguard.sh/register, and keep building your skills in the Safeguard Academy.