refactorx
v0.1.3
Published
Lokal LLM (Ollama) ile kod kalitesi ve güvenlik analizi yapan CLI aracı
Maintainers
Readme
RefactorX
Semantic security scanner with data-flow analysis, path sensitivity, and local LLM support.
RefactorX goes beyond pattern matching. It builds a semantic model of your project — indexing routes, tracing tainted data from source to sink across function boundaries, evaluating guards and validators in order — and produces ranked, evidence-backed security findings ready for CI pipelines.
Why RefactorX?
Most security scanners apply regular expressions to source text. They find what they pattern-match and nothing more. RefactorX takes a different approach:
| Capability | Regex scanner | RefactorX | |---|---|---| | Source → sink tracing | ✗ | ✓ DataFlow Engine | | Ordering-aware analysis | ✗ | ✓ Path Sensitivity | | Guard clause detection | ✗ | ✓ CFG analysis | | Validation before/after sink | ✗ | ✓ Statement ordering | | Framework route resolution | ✗ | ✓ Express / NestJS | | SSRF source classification | ✗ | ✓ user-controls-url/host/path | | Evidence for every finding | ✗ | ✓ source + path + sink | | Local-first, no data egress | varies | ✓ Ollama + local rules | | CI baseline support | varies | ✓ stable fingerprints |
RefactorX is designed for teams that want actionable security findings, not noise.
Features
Semantic Engine
- Project Indexer — discovers routes, controllers, middleware, auth signals, and validation patterns
- Semantic Graph — maps controllers, services, and their dependencies
- Symbol Table — tracks declarations and references across files
- Call Graph — follows function call chains to connect sources to sinks
- DataFlow Engine — intra-procedural + interprocedural taint propagation
- Path Sensitivity — detects whether validation, sanitizers, and guard clauses appear before or after the sink
- Helper Propagation — traces taint through user-defined helper functions
- DataFlow Evidence — every finding includes
source → steps → sinkwith line numbers
Security Rules
- SQL Injection (CWE-89)
- Server-Side Request Forgery (CWE-918)
- Cross-Site Scripting (CWE-79)
- Path Traversal (CWE-22)
- Command Injection (CWE-78)
- Code Injection / eval (CWE-95)
- Authentication & Access Control (OWASP A07, A01)
- Sensitive Data Exposure (CWE-312, CWE-798)
- Cryptography Weaknesses (CWE-327, CWE-338)
- Payment Flow Security
- Supply Chain (dependency confusion, typosquatting)
- AI-generated code anti-patterns
- React Native mobile security
- ReDoS, unhandled promises, resource leaks
LLM Context Packs
Instead of sending entire files to an LLM, RefactorX extracts a minimal, structured context pack per finding:
- Source expression and location
- Sink expression and CWE
- Taint propagation path
- Auth and validation status
- Risk reasons (why this is high priority)
- Relevant code snippet (not the whole file)
This dramatically reduces token usage while giving the LLM the exact context it needs.
CI / CD
- Security profile — suppresses code-quality noise in pipeline output
- CI mode — deterministic exit codes based on severity threshold
- Baseline — fingerprint existing findings; fail only on new issues
- SARIF — GitHub Code Scanning compatible output
- JSON — machine-readable findings with full evidence
- Markdown — human-readable reports written to
SECURITY.md - HTML — standalone report for sharing
Installation
npm install --global refactorxRequires Node.js ≥ 20. Works without an LLM — all static analysis and security rules run offline.
For LLM-powered review, install Ollama and pull a model:
ollama pull codellama
ollama serveQuick Start
# Run all static analysis and security rules
refactorx analyze .
# Security-only profile (suppresses code quality noise)
refactorx analyze . --profile security
# Use semantic context packs for LLM prompts (requires Ollama)
refactorx analyze . --llm-context semantic
# CI mode — exit 1 if any HIGH or CRITICAL findings
refactorx analyze . --profile security --ci --fail-on high
# Create a baseline from current findings
refactorx analyze . --profile security --update-baseline refactorx-baseline.json
# CI with baseline — fail only on NEW findings
refactorx analyze . --profile security --baseline refactorx-baseline.json --ci --fail-on highCLI Reference
refactorx analyze <path> [options]Core
| Option | Default | Description |
|---|---|---|
| --profile <mode> | full | Report profile: full, security, quality |
| --scan <type> | (none) | Review persona(s); repeat or comma-separate; all for every persona |
| --priority <level> | low | Only show findings at or above: critical, high, medium, low |
| --output <format> | md | Output format(s): md, json, html, sarif, terminal, all |
| --out <path> | — | Write output to a file or directory |
Analysis
| Option | Default | Description |
|---|---|---|
| --model <model> | codellama | Ollama model to use |
| --llm-context <mode> | raw | LLM context mode: raw (full file) or semantic (context packs) |
| --deep-scan | false | Send every source file to the LLM regardless of selector score |
| --fast | false | Speed-optimized mode: shorter prompts, 15 s timeout, reduced context |
| --lang <lang> | — | Skip auto-detection; set language: ts, py, go, rust, java |
| --include-tests | false | Include test files in LLM analysis |
| --no-cache | false | Bypass LLM result cache |
CI / Baseline
| Option | Default | Description |
|---|---|---|
| --ci | false | Enable CI mode; sets exit code based on --fail-on threshold |
| --fail-on <level> | high | Severity threshold: critical, high, medium, low |
| --baseline <file> | — | Load a baseline; CI fails only on new findings |
| --update-baseline <file> | — | Write current findings as a new baseline |
Advanced
| Option | Description |
|---|---|
| --ignore <glob> | Exclude paths matching glob (repeatable) |
| --max-depth <n> | Directory traversal depth limit (default: 10) |
| --concurrency <n> | Parallel analysis workers (default: 4) |
| --watch | Re-analyze on file changes |
| --extra-prompt <text> | Append custom instruction to all LLM prompts |
| --prompt-file <file> | Load custom prompt from a Markdown file |
| --verbose | Print each LLM request, file decision, and finding as it is found |
| --dry-run | Analyze without writing any output files |
Analysis Profiles
| Profile | What it shows | Best for |
|---|---|---|
| full | All findings: security + code quality | Local development review |
| security | Security findings only | CI pipelines, audits |
| quality | Code quality findings only | Code review gates |
refactorx analyze . --profile security --output json --out report.jsonSemantic Engine Architecture
flowchart LR
Project["Project Files"] --> Scanner["File Scanner\n(.gitignore aware)"]
Scanner --> Indexer["Project Indexer\n(routes, auth, validation)"]
Indexer --> SGraph["Semantic Graph\n(controllers, services)"]
SGraph --> CallGraph["Call Graph\n(function chains)"]
SGraph --> SymTable["Symbol Table\n(declarations)"]
CallGraph --> DFEngine["DataFlow Engine\n(taint propagation)"]
DFEngine --> CFG["Path Sensitivity\n(guard / validation order)"]
CFG --> Evidence["DataFlow Evidence\n(source → sink + steps)"]
Evidence --> Risk["Risk Engine\n(severity + SSRF class)"]
Risk --> Ranking["Finding Ranking\n(score-based)"]
Ranking --> Report["Report\nJSON / MD / HTML / SARIF"]
Risk --> CtxPack["LLM Context Pack\n(minimal token budget)"]
CtxPack --> LLM["Ollama LLM\n(optional)"]LLM Context Packs
When --llm-context semantic is used, RefactorX does not send the entire source file to the LLM. Instead, it builds a minimal context pack per finding that contains only what the model needs:
{
"finding": {
"rule": "SEM-DF-SQL-001",
"severity": "CRITICAL",
"title": "SQL Injection — user input reaches SQL sink"
},
"source": {
"expression": "req.body.email",
"line": 12
},
"sink": {
"expression": "db.query(sql)",
"cwe": "CWE-89",
"line": 28
},
"pathSensitivity": {
"validationBeforeSink": false,
"guardBeforeSink": false
},
"riskReasons": ["public route", "user input", "sensitive sink", "no validation"],
"snippet": "const email = req.body.email;\nconst sql = `SELECT * FROM users WHERE email='${email}'`;\nawait db.query(sql);"
}This reduces token usage by 60–80% compared to full-file prompts while providing the LLM with more targeted context.
Scan Personas
RefactorX includes specialized review personas that focus LLM analysis on specific threat models:
| Persona | Focus area |
|---|---|
| security-researcher | Systematic OWASP-methodology scan |
| attacker-db | Database exploitation perspective |
| attacker-routes | Unauthorized route access attempts |
| insider-threat | Internal sabotage scenarios |
| data-privacy | GDPR / data protection compliance |
| supply-chain | Dependency and package security |
| crypto-auditor | Cryptography weaknesses |
| session-auth | Session and authentication flaws |
| input-fuzzer | Input validation gaps |
| business-logic | Business logic vulnerabilities |
| payment-auditor | Payment flow security (auto-added when payment files detected) |
| api-security | Pre-auth endpoints, header trust, BOLA/BFLA |
| ai-review | Systematic mistakes in AI-generated code |
# List all personas with descriptions
refactorx scans
# Run multiple personas
refactorx analyze . --scan attacker-db --scan attacker-routes
# Run all personas
refactorx analyze . --scan allSupported Languages
| Language | Detection | Static Rules | Language Rules | Semantic DataFlow | |---|---|---|---|---| | TypeScript | ✓ | ✓ | ✓ | ✓ | | JavaScript | ✓ | ✓ | — | ✓ | | Python | ✓ | ✓ | ✓ | — | | Go | ✓ | ✓ | ✓ | — | | Java | ✓ | ✓ | ✓ | — | | Rust | ✓ | ✓ | ✓ | — | | Ruby | ✓ | Partial | — | — |
Note: Semantic DataFlow analysis (intra/interprocedural taint, path sensitivity) currently targets TypeScript and JavaScript. Other languages receive static rule coverage via dedicated rule sets.
Supported Frameworks
| Framework | Detection | Route Resolution | Auth Detection | Semantic DataFlow | |---|---|---|---|---| | Express.js | ✓ | ✓ | ✓ | ✓ | | NestJS | ✓ | ✓ | ✓ | ✓ | | Next.js | ✓ | Partial | — | ✓ | | React Native | ✓ | — | — | ✓ (mobile rules) | | Fastify | Detection only | — | — | — | | Vite | Detection only | — | — | — |
Output Formats
JSON
Full machine-readable output including DataFlow evidence, path sensitivity, SSRF classification, baseline status, and rank score:
refactorx analyze . --output json --out report.json{
"findings": [
{
"rule": "SEM-DF-SQL-001",
"severity": "CRITICAL",
"confidence": "high",
"rankScore": 203,
"rankReasons": ["semantic-data-flow", "data-flow-evidence", "critical-severity"],
"dataFlowEvidence": {
"source": { "expression": "req.body.email", "line": 12 },
"sink": { "expression": "db.query(sql)", "cwe": "CWE-89", "line": 28 },
"pathSensitivity": {
"validationBeforeSink": false,
"guardBeforeSink": false
}
},
"baselineStatus": "new"
}
]
}SARIF
GitHub Code Scanning compatible:
refactorx analyze . --output sarif --out refactorx.sarifMarkdown
Written to SECURITY.md by default. Suitable for committing to the repository as a security posture snapshot.
HTML
Standalone HTML report with all findings, evidence, and metadata:
refactorx analyze . --output html --out security-report.htmlCI / CD Integration
Basic CI
refactorx analyze . --profile security --ci --fail-on highExit codes: 0 = passed, 1 = findings at or above threshold.
CI output:
CI mode enabled
Profile: security
Fail threshold: HIGH
Critical: 2
High: 5
Medium: 11
Low: 4
Result: FAILED
Reason: 7 findings at or above HIGHWith Baseline
A baseline lets you acknowledge existing debt and fail the pipeline only when new findings appear.
Step 1 — Create the baseline (run once, commit the file):
refactorx analyze . --profile security --update-baseline refactorx-baseline.json
git add refactorx-baseline.json
git commit -m "chore: add refactorx security baseline"Step 2 — Use the baseline in CI:
refactorx analyze . --profile security --baseline refactorx-baseline.json --ci --fail-on highOutput when only existing findings are present:
Baseline: refactorx-baseline.json
Existing findings: 120
New findings: 0
Result: PASSEDOutput when new findings appear:
Baseline: refactorx-baseline.json
Existing findings: 120
New findings: 3
CI mode enabled
New Critical: 1
New High: 2
Result: FAILED
Reason: 3 new findings at or above HIGHGitHub Actions
- name: Security scan
run: |
npm install -g refactorx
refactorx analyze . \
--profile security \
--baseline refactorx-baseline.json \
--ci --fail-on high \
--output sarif --out refactorx.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: refactorx.sarifFinding Fingerprints
RefactorX uses content-based fingerprinting for baseline stability:
fingerprint = SHA256(ruleId + category + filePath + sinkExpression + sourceExpression + title + cwe)Line numbers are not part of the hash. Small refactors that shift line numbers do not invalidate the baseline.
Path Sensitivity
RefactorX understands the order of statements. These two patterns produce different findings:
// Pattern A — validation BEFORE sink → confidence reduced to medium, status: needs-review
const dto = UserSchema.parse(req.body);
await db.query(`SELECT * FROM users WHERE email='${req.body.email}'`);
// Pattern B — validation AFTER sink → full severity, status: action-required
await db.query(`SELECT * FROM users WHERE email='${req.body.email}'`);
const dto = UserSchema.parse(req.body);Pattern A: validationBeforeSink: true → severity downgraded, confidence medium
Pattern B: validationBeforeSink: false → full severity maintained
The same logic applies to sanitizers and auth guard clauses (if (!req.user) return).
SSRF Classification
SSRF findings are classified by what portion of the URL the attacker controls:
| Classification | Meaning | Typical severity |
|---|---|---|
| user-controls-url | Full URL from user input | CRITICAL |
| user-controls-host | Hostname from user input | HIGH |
| user-controls-path | Path component from user input | HIGH |
| user-controls-query | Query string from user input | MEDIUM |
| static-host-with-user-path | Static host, user-controlled path | MEDIUM (downgraded) |
| static-host-with-user-query | Static host, user-controlled query | LOW (downgraded) |
Current Limitations
- Interprocedural analysis across files is functional for NestJS (via call graph) but still evolving for Express; helper propagation works within a single file.
- Semantic DataFlow analysis targets TypeScript and JavaScript. Python, Go, Java, and Rust receive static rule coverage without taint propagation.
- Ruby has no dedicated rule set; only generic injection and secrets patterns apply.
- Fastify, Koa, Hapi are detected but have no dedicated framework resolvers.
- Path sensitivity uses statement-ordering analysis, not a full dominator tree. Complex control flow may produce imprecise results.
- LLM analysis requires Ollama running locally. All static analysis and security rules work without it.
Roadmap
- [ ] Cross-file taint propagation for TypeScript/JavaScript
- [ ] Python semantic DataFlow engine
- [ ] Fastify and Koa framework resolvers
- [ ] Dominator-tree-based path sensitivity
- [ ] VSCode extension with inline findings
- [ ] GitHub Action (official)
- [ ] Ruby rule set
- [ ] GraphQL security rules
Contributing
Contributions are welcome. The most useful areas:
- Rule sets — new security rules for uncovered patterns or languages
- Framework resolvers — route extraction for Fastify, Koa, Django, Rails, Spring Boot
- Language analyzers — Python and Go DataFlow engines
- Test coverage — integration tests against real-world project samples
Please open an issue before starting a large change.
git clone https://github.com/your-org/refactorx
cd refactorx
npm install
npm test # 808 tests
npm run lint # ESLint
npm run build # TypeScript compileLicense
MIT — see LICENSE.
