Running an Audit¶
The ges audit command is the core of GESF. It scans your actual source code with 8 independent scanners and produces actionable findings linked to compliance controls.
Basic Usage¶
What Happens During an Audit¶
- Walks your project directory (skipping
node_modules,.git,dist,build,.ges) - Reads source files (up to 1MB each, all text-based languages)
- Runs 8 scanners:
- Secrets Scanner — Hardcoded passwords, API keys, tokens, private keys
- Crypto Scanner — MD5, SHA1, weak encryption, disabled TLS (JavaScript, Python, Go, Java, Rust)
- Code Security Scanner — SQL injection, XSS, eval/code injection (JavaScript, Python, Go, Rust)
- Auth Scanner — Routes without auth, missing rate limiting, wildcard CORS
- Config Scanner — Missing helmet/cors, .env secrets, Docker issues
- Database Scanner — Missing audit columns, missing soft delete
- IaC Scanner — Terraform/CloudFormation misconfigurations, open ports, public S3 (see IaC Scanner)
- Dependency Analysis — Vulnerabilities, deprecated packages, license issues (see Dependency Analysis)
- Deduplicates findings
- Maps findings to compliance control IDs (e.g.,
GDPR-ART32-002) - Updates your compliance score in
.ges/score.json
Example: Vulnerable Project¶
Given this source code:
const crypto = require('crypto');
function hash(password) {
return crypto.createHash('md5').update(password).digest('hex');
}
app.get('/users', (req, res) => {
db.query("SELECT * FROM users WHERE id = " + req.params.id);
});
Running ges audit produces:
GESF Compliance Audit
────────────────────
Scanning project files...
Scanned 3 files
── Findings ─────────────────────
Total findings: 4
Critical: 3 High: 1 Medium: 0 Low: 0
[SECRETS]
[CRIT] Hardcoded password detected (src/config.js:1)
DB_PASSWORD = "my-s..."
[ENCRYPTION]
[CRIT] MD5 hash algorithm detected (src/auth.js:3)
[INJECTION]
[CRIT] SQL injection via string concatenation (src/routes.js:2)
[AUTHENTICATION]
[HIGH] Route without auth middleware (src/routes.js:1)
── Compliance Score ──────────────
GDPR ................ 42%
OWASP ............... 55%
Overall ............. 49%
Example: Clean Project¶
After fixing all issues:
const argon2 = require('argon2');
async function hash(password) {
return argon2.hash(password);
}
app.get('/users', authenticate, (req, res) => {
db.query("SELECT * FROM users WHERE id = $1", [req.params.id]);
});
Running ges audit again:
GESF Compliance Audit
────────────────────
Scanning project files...
Scanned 3 files
── Findings ─────────────────────
Total findings: 0
Critical: 0 High: 0 Medium: 0 Low: 0
✓ No security or compliance issues found in source code.
── Compliance Score ──────────────
GDPR ................ 72%
OWASP ............... 65%
Overall ............. 69%
CI Mode¶
Use --ci for CI/CD pipelines. Exits with code 1 if critical findings exist:
JSON Output¶
Use --json for machine-readable output:
Returns a JSON object:
{
"findings": [
{
"ruleId": "secrets-hardcoded-password",
"severity": "critical",
"category": "secrets",
"title": "Hardcoded password detected",
"file": "src/config.js",
"line": 1,
"evidence": "password = \"***masked***\"",
"controlIds": ["GDPR-ART32-002"],
"fix": "Use environment variables or a secrets manager"
}
],
"score": {
"overall": 49,
"frameworks": { "GDPR": { "score": 42 }, "OWASP": { "score": 55 } }
}
}
Understanding Findings¶
Each finding contains:
| Field | Description |
|---|---|
title |
Human-readable description of the issue |
severity |
critical, high, medium, or low |
category |
secrets, encryption, injection, xss, authentication, config, database, infrastructure, dependency |
file |
File path relative to project root |
line |
Line number where the issue was detected |
evidence |
The actual code snippet that triggered the finding (secrets are masked) |
controlIds |
Compliance control IDs this finding violates |
fix |
Suggested fix |
Severity Levels¶
| Severity | Meaning | Required Action |
|---|---|---|
| Critical | Immediate security risk | Must fix before deployment |
| High | Significant compliance gap | Should fix in current sprint |
| Medium | Notable concern | Should fix soon |
| Low | Minor improvement | Fix when convenient |
Excluding Files with .gesignore¶
Create a .gesignore file in your project root to exclude specific files and directories from the audit. It uses the same syntax as .gitignore:
# Exclude test fixtures with intentional vulnerabilities
test/fixtures/
tests/
# Exclude generated code
generated/
*.generated.js
# Exclude vendor directories
vendor/
third-party/
# Exclude specific files
config/legacy.js
Pattern Types¶
| Pattern | Matches |
|---|---|
dir/ |
Entire directory and all contents |
*.ext |
All files with the extension |
*pattern* |
Wildcard matching |
path/to/file |
Specific file |
# comment |
Comment line (ignored) |
The .gesignore file is useful for:
- Test fixtures that intentionally contain vulnerabilities
- Generated/vendored code you do not control
- Legacy code under separate remediation plans
- Third-party libraries bundled into your repo
Incremental Audit¶
For large projects, GESF supports incremental auditing — only re-scanning files that have changed since the last audit. This is used internally by the git hooks and auto-fix features for faster feedback.
The incremental audit:
- Computes a hash of each file's content
- Compares against the cached hash from the previous run
- Only re-scans files whose hash has changed
- Merges new findings with cached findings from unchanged files
This significantly reduces scan time for projects with many files where only a few change between commits.
Exercise: Audit a Real Project
- Go to one of your existing projects (or use the vulnerable demo from Quick Start)
- Run
ges audit - Count the number of findings by severity
- Pick the top 3 critical findings and fix them
- Re-run
ges auditand compare the output
Questions to ask yourself
- Which scanner found the most issues?
- Are there any findings you disagree with (false positives)?
- Which finding would be the most dangerous if exploited?
Exercise: Use .gesignore to Exclude False Positives
- Using the project from the previous exercise, identify any false positives or test fixtures with intentional vulnerabilities
- Create a
.gesignorefile:
echo "# Exclude test fixtures" > .gesignore
echo "test/fixtures/" >> .gesignore
echo "tests/" >> .gesignore
- Re-run
ges audit— the excluded files should no longer generate findings - Compare the finding count before and after
Questions
- How many findings were eliminated by the
.gesignorefile? - When would it be inappropriate to use
.gesignoreto suppress findings? - What is the risk of over-using
.gesignore?
Exercise: Test Each Scanner Individually
Create a test file that triggers each scanner exactly once:
mkdir /tmp/scanner-test && cd /tmp/scanner-test
echo '{"name":"scanner-test"}' > package.json
ges init -n "Scanner Test" -t generic-web-application -f "GDPR,OWASP"
Now run ges audit — you should see 6 findings, one from each scanner category.
Exercise: Fix Findings and Track Score Improvement
- Start with the vulnerable project from the Quick Start
- Run
ges auditand note your score (e.g., 49%) - Fix one category at a time:
- First, fix all SECRETS findings → re-audit → note new score
- Then fix all ENCRYPTION findings → re-audit → note new score
- Then fix all INJECTION findings → re-audit → note new score
- Plot your score improvement:
| Fix Applied | Criticals Remaining | Score |
|---|---|---|
| None (baseline) | 6 | 49% |
| Secrets fixed | 3 | 55% |
| Crypto fixed | 2 | 62% |
| Injection fixed | 0 | 69% |
| Auth + Config fixed | 0 | 78% |