Skip to content

graudit

graudit (grep rough audit) is a lightweight, open-source static application security testing (SAST) tool that performs source code analysis using grep patterns. It identifies potential vulnerabilities, dangerous coding practices, code smells, and security issues by pattern matching against customizable rule sets. graudit is language-agnostic and supports multiple programming languages including Python, PHP, Java, C/C++, JavaScript, Ruby, and others.

The tool is designed for rapid security audits during penetration testing, code review processes, and continuous integration/continuous deployment (CI/CD) pipelines. It’s particularly useful for identifying common vulnerability patterns without requiring sophisticated semantic analysis.

# Install from repository
sudo apt-get update
sudo apt-get install graudit

# Or install from source
git clone https://github.com/presidentbeef/graudit.git
cd graudit
sudo ./install.sh

# Verify installation
graudit -v
# Using Homebrew
brew install graudit

# Or from source
git clone https://github.com/presidentbeef/graudit.git
cd graudit
sudo bash install.sh
# Using Git Bash or WSL
git clone https://github.com/presidentbeef/graudit.git
cd graudit
bash install.sh

# Alternative: Use WSL (Windows Subsystem for Linux)
wsl
sudo apt-get install graudit
# Scan single file
graudit myfile.php

# Scan all PHP files in directory
graudit *.php

# Scan entire directory recursively
graudit -r /path/to/code

# Quiet mode (findings only)
graudit -q file.py
# Standard output
graudit file.php

# Verbose output (more context)
graudit -v file.php

# Log output to file
graudit -l results.log file.php

# XML output
graudit -x results.xml file.php
DatabaseLanguageFocusCommand
defaultMultiGeneral vulnerabilitiesgraudit -d default file
phpPHPPHP-specific issuesgraudit -d php file.php
pythonPythonPython vulnerabilitiesgraudit -d python file.py
javaJavaJava security issuesgraudit -d java file.java
cC/C++Memory, buffer issuesgraudit -d c file.c
jsJavaScriptJS/Node issuesgraudit -d js file.js
rubyRubyRuby vulnerabilitiesgraudit -d ruby file.rb
customAnyUser-defined patternsgraudit -d ./custom.db file
# List available databases
graudit -l

# Using specific database
graudit -d php index.php

# View database location
graudit -g

# List all rules in database
graudit -s php | head -20
# Scan PHP file with PHP database
graudit -d php index.php

# Scan all PHP files
find . -name "*.php" -exec graudit -d php {} \;

# Common PHP vulnerabilities detected:
# - SQL injection (mysql_query, mysqli, PDO)
# - Command injection (exec, system, passthru)
# - XSS (echo, print without escaping)
# - File inclusion (include, require)
# - Insecure functions (eval, create_function)
# Scan Python file
graudit -d python script.py

# Scan all Python files
find . -name "*.py" | xargs graudit -d python

# Python vulnerabilities detected:
# - SQL injection (execute, query)
# - Command execution (os.system, subprocess)
# - Insecure deserialization (pickle)
# - Hardcoded credentials
# - Unsafe imports
# Scan Java source files
graudit -d java *.java

# Recursive Java scan
find . -name "*.java" | xargs graudit -d java

# Java issues detected:
# - SQL injection patterns
# - Weak cryptography
# - Insecure deserialization
# - Command injection
# Scan JavaScript files
graudit -d js app.js

# Scan Node.js project
find . -name "*.js" | xargs graudit -d js

# Common findings:
# - eval() usage
# - require() with variables
# - Insecure crypto
# - Command execution
# Scan entire project
graudit -r /path/to/project

# Recursive with specific database
graudit -r -d php /var/www/html

# Recursive excluding directories
find /path -type f -name "*.php" ! -path "*/vendor/*" ! -path "*/node_modules/*" | xargs graudit -d php
# Scan mixed PHP and JavaScript project
graudit -r -d default /var/www/app

# Sequential scanning with different databases
for file in $(find . -name "*.php"); do graudit -d php "$file"; done
for file in $(find . -name "*.js"); do graudit -d js "$file"; done
# Show only first 10 matches per file
graudit file.php | head -10

# Filter specific vulnerability type
graudit -v file.php | grep "SQL"

# Count total vulnerabilities
graudit -r /code | grep -c "Found"
# View default database structure
cat /usr/share/graudit/databases/default.db

# Create custom database
cat > custom.db << 'EOF'
# Custom Security Rules
# Format: regex_pattern

# Detect hardcoded API keys
[A-Za-z0-9]{40}

# Detect TODO comments
TODO.*FIXME

# Detect insecure protocols
http://[^s]

# Detect weak encryption
MD5|SHA1
EOF

# Use custom database
graudit -d ./custom.db file.php
# Database syntax:
# Lines starting with # are comments
# Each rule is a grep regex pattern
# Patterns are case-sensitive by default

# Example rule for SQL injection
SELECT.*FROM.*WHERE

# Pattern for command execution
exec\s*\(|system\s*\(|passthru\s*\(

# Pattern for file operations
fopen|file_get_contents|readfile

# Pattern for eval
eval\s*\(|create_function
# Test patterns with grep before adding to database
grep -n "SELECT.*FROM" *.php

# Test regex pattern syntax
grep -E "[0-9]{3}-[0-9]{2}-[0-9]{4}" *.txt

# Use graudit's verbose output
graudit -v -d custom.db file.php
# 1. Extract source code from target
scp -r user@target:/var/www/app ./target_code

# 2. Run graudit audit
graudit -r -d default ./target_code > audit_results.txt

# 3. Review findings
cat audit_results.txt | sort | uniq

# 4. Verify with manual inspection
vim target_code/vulnerable_file.php
#!/bin/bash
# Comprehensive code audit script

PROJECT_PATH=$1
REPORT_FILE="graudit_report_$(date +%Y%m%d_%H%M%S).txt"

echo "=== graudit Security Audit Report ===" > $REPORT_FILE
echo "Project: $PROJECT_PATH" >> $REPORT_FILE
echo "Date: $(date)" >> $REPORT_FILE
echo "" >> $REPORT_FILE

echo "[PHP Files]" >> $REPORT_FILE
find $PROJECT_PATH -name "*.php" | xargs graudit -d php >> $REPORT_FILE

echo "[Python Files]" >> $REPORT_FILE
find $PROJECT_PATH -name "*.py" | xargs graudit -d python >> $REPORT_FILE

echo "[JavaScript Files]" >> $REPORT_FILE
find $PROJECT_PATH -name "*.js" | xargs graudit -d js >> $REPORT_FILE

echo "Report saved to: $REPORT_FILE"
# Typical graudit output format:
# /path/to/file.php:123: Found: dangerous_pattern

graudit file.php
/path/to/file.php:45: Found: exec(
/path/to/file.php:67: Found: $_GET
/path/to/file.php:89: Found: eval(
# Count findings by type
graudit -r /code | awk -F': Found: ' '{print $2}' | sort | uniq -c | sort -rn

# Extract filename and line number
graudit -r /code | awk -F':' '{print $1":"$2}' | sort -u

# Create CSV report
graudit -r /code | awk -F': Found: ' '{print $1","$2}' > audit.csv
# Graudit detects:
$query = "SELECT * FROM users WHERE id=" . $_GET['id'];
$db->query("SELECT * FROM users WHERE id=".$_POST['id']);
mysqli_query($conn, "SELECT * FROM WHERE id=$id");

# Grep pattern to find vulnerable code
grep -n "SELECT.*FROM.*WHERE.*\$" *.php
# Graudit identifies:
system($_GET['cmd']);
exec($_POST['command']);
passthru(user_input);
shell_exec($cmd);

# Manual verification
grep -n "exec\|system\|passthru\|shell_exec" *.php
# Detected patterns:
echo $_GET['name'];
print $_POST['comment'];
<div><?php echo $user_input; ?></div>

# Find echo/print with user input
grep -n "echo\s*\$_\|print\s*\$_" *.php
# Python detection
pickle.loads(user_data)
json.loads(untrusted_json)

# PHP detection
unserialize($_GET['data']);

# Search for patterns
grep -n "unserialize\|pickle.loads" *.php *.py
#!/bin/bash
# .git/hooks/pre-commit

echo "Running graudit security audit..."
CHANGED_FILES=$(git diff --cached --name-only)

for file in $CHANGED_FILES; do
    if [[ $file == *.php ]]; then
        graudit -d php "$file" && {
            echo "Security issues found in $file"
            exit 1
        }
    fi
done

exit 0
# Example GitHub Actions workflow
name: Code Security Audit
on: [push, pull_request]

jobs:
  graudit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Install graudit
        run: sudo apt-get install graudit
      - name: Run graudit
        run: graudit -r . > audit_results.txt
      - name: Upload results
        uses: actions/upload-artifact@v2
        with:
          name: graudit-report
          path: audit_results.txt
# graudit may flag legitimate code:

# False positive 1: Comment containing SQL
# "TODO: Implement SELECT query for users table"

# False positive 2: String literal
$example = "SELECT * FROM users";

# False positive 3: Log messages
echo "System executing backup script";
# Exclude comment-only matches
graudit -r /code | grep -v "^[[:space:]]*//"

# Exclude specific files
find /code -name "*.php" ! -path "*/test/*" ! -path "*/vendor/*" | xargs graudit -d php

# Manual review and whitelist
graudit -v file.php | less
# Use 'v' flag for context
# Exclude large directories
graudit -r /code --exclude=vendor,node_modules,dist

# Parallel scanning
find . -name "*.php" | parallel graudit -d php

# Sample scanning (10% of files)
find . -name "*.php" | shuf | head -10% | xargs graudit -d php
# Measure scan time
time graudit -r /code

# Count files scanned
find /code -type f \( -name "*.php" -o -name "*.js" \) | wc -l

# Generate statistics
echo "Total files: $(find /code -type f | wc -l)"
echo "PHP files: $(find /code -name "*.php" | wc -l)"
echo "Findings: $(graudit -r /code | wc -l)"
IssueCauseSolution
Database not foundWrong pathCheck /usr/share/graudit/databases/
No resultsEmpty file listVerify file extensions match database
Too many false positivesOverly broad patternsUse more specific database
Permission deniedFile access issueCheck file permissions, use sudo
Pattern not matchingRegex syntax errorTest with grep first
# Verbose output for debugging
graudit -v -d php file.php

# Show pattern matching details
graudit -v file.php 2>&1 | tee debug_output.txt

# List all patterns in database
graudit -s default | head -20
# When auditing third-party code:
1. Get written permission before auditing
2. Report findings responsibly
3. Use secure channels for reporting
4. Allow time for patching before disclosure
5. Keep findings confidential
# Ensure compliance with regulations:
# - Only audit code you have permission to audit
# - Document your authorization
# - Follow responsible disclosure practices
# - Adhere to CFAA and local regulations
# - Obtain client approval for testing
# Pattern: Detect unescaped output
<\?php\s+echo\s+\$(?!.*htmlspecialchars)

# Pattern: Detect hardcoded credentials
(password|api_key|secret)\s*=\s*['"][^'"]{8,}['"]

# Pattern: Detect weak algorithms
(md5|sha1|base64_encode)\s*\(

# Pattern: Detect remote code inclusion
(include|require)_once\s*\(\s*\$

# Test patterns
grep -E "pattern_here" file.php
# Create project-specific database
cat > project_security.db << 'EOF'
# Project-specific vulnerabilities

# Custom API endpoints check
/api/admin

# Framework-specific issues
Django.*raw_sql
Flask.*render_template_string

# Database ORM issues
.filter\(.*user_input\)
.execute\(.*user_input\)

# Logging sensitive data
logger\.debug.*password
console\.log.*token
EOF

graudit -d ./project_security.db -r ./src
# Use graudit alongside other tools
graudit -r /code > graudit_results.txt
semgrep -c p/security-audit /code > semgrep_results.txt
bandit -r /code > bandit_results.txt

# Merge and deduplicate results
cat *_results.txt | sort | uniq > combined_audit.txt
# Export to HTML report
graudit -r /code | awk '{print "<tr><td>" $0 "</td></tr>"}' | \
  sed '1i<table>' | sed '$a</table>' > report.html

# Export to JSON
graudit -v -r /code | jq -R -s '{findings: split("\n")}'

# Export to Slack
graudit -r /code | while read line; do
  curl -X POST -H 'Content-type: application/json' \
    --data "{'text':'$line'}" $SLACK_WEBHOOK_URL
done