A small Static Application Security Testing (SAST) tool written in pure
Python. It scans a directory of .py files and reports every use of an
unsafe function (such as eval, exec, or pickle.loads) — the kind of
pattern that can lead to remote code execution in production software.
This repository is the coursework for the Secure Software Development unit. It contains the working tool, the documentation explaining how it was built, a reusable pseudocode formula for solving this whole class of problems, and a worked example showing that formula applied to the graded lab.
Result: the lab script
static_final.pywas graded 50 / 50 in CodeGrade.
Given a folder of Python source code, the tool:
- Collects every
.pyfile under the folder (recursively). - Parses each file into an Abstract Syntax Tree (AST) — a structured representation of the code.
- Checks each node against a list of unsafe function names.
- Reports every match with its file name, line number, and a description.
Because it analyses the AST rather than searching raw text, it does not get fooled by comments, strings, or variables that merely contain a risky word — it only flags genuine function calls.
Input file test_dir/vulnerable_sample.py:
# vulnerable_sample.py
user_input = "2 + 2"
result = eval(user_input)
print(result)Output:
Vulnerabilities found:
File: test_dir/vulnerable_sample.py, Line: 3, Issue: Use of unsafe function 'eval'
A file with no unsafe calls prints:
No vulnerabilities found.
secure-sdlc-static-analyzer/
├── static_final.py # the tool (the graded lab deliverable)
├── test_dir/
│ └── vulnerable_sample.py # a known-bad sample for testing
├── docs/
│ ├── HOW_TO_BUILD_THE_SCRIPT.md # step-by-step build & explanation guide
│ ├── PSEUDOCODE_GENERAL.md # reusable "formula" for similar problems
│ └── PSEUDOCODE_SOLVED_EXAMPLE.md # the lab solved using that formula
├── screenshots/ # add VS Code run + CodeGrade 50/50 here
├── .gitignore
└── README.md
- Python 3.6+ (uses only the standard library —
osandast). - No third-party packages, no
pip installneeded.
Check your version:
python --versiongit clone https://github.com/<your-username>/secure-sdlc-static-analyzer.git
cd secure-sdlc-static-analyzerOpen static_final.py and look at the bottom:
if __name__ == "__main__":
main("your_source_code_directory")Change "your_source_code_directory" to the folder you want to scan. To try the
included sample, use "test_dir":
if __name__ == "__main__":
main("test_dir")python static_final.pyExpected output with the sample:
Vulnerabilities found:
File: test_dir/vulnerable_sample.py, Line: 3, Issue: Use of unsafe function 'eval'
Windows note: if you see
Could not find platform independent libraries <prefix>, that is a harmless Python environment warning on some installs. It does not affect the results — the scan still runs.
The script is five small functions plus an entry point. Each does one job, so you can read, test, or reuse them independently.
| Function | Responsibility |
|---|---|
collect_source_files(directory, extension) |
Recursively find files to scan. |
parse_source_code(file_path) |
Read a file and build its AST; skip files with syntax errors instead of crashing. |
unsafe_functions (global list) |
The rule set — the names considered dangerous. |
is_vulnerable_function(node) |
Decide whether one AST node is a call to an unsafe function (handles both eval(...) and dotted pickle.loads(...)). |
analyze_ast(tree, file_path) |
Walk the whole tree and collect every match as a {file, line, issue} record. |
main(directory) |
Orchestrate collect → parse → analyze → report. |
For the full explanation — including why the AST approach is used and a
common bug to avoid with dotted names — see
docs/HOW_TO_BUILD_THE_SCRIPT.md.
This tool is intentionally structured as a reusable formula (see
docs/PSEUDOCODE_GENERAL.md). To adapt it to a
similar problem you usually change only one or two things:
- Detect more functions → add names to the
unsafe_functionslist (e.g."os.system","subprocess.call","input"). - Scan a different file type → change the
extensionargument. - Output to a file → modify
mainto write JSON or CSV instead of printing. - Detect non-call patterns → extend
is_vulnerable_functionto inspect other AST node types.
Because the traversal is generic and the rules are just data, these changes do not require rewriting the tool.
This tool is a hands-on example of building security into the Software Development Lifecycle (SDLC) rather than bolting it on at the end. Automated static analysis like this belongs in the testing phase and, in real teams, runs automatically inside a CI/CD pipeline (DevSecOps) so that risky code is caught before it ever reaches production.
Educational use. Created as coursework for the Secure Software Development unit.
