Skip to content

Commit 35f3cf1

Browse files
authored
feat(cli): Implement scan, query, and ci commands with Python DSL integration (#361)
Implements CLI commands for executing Python DSL security rules against codebases. Adds scan command for CI/CD vulnerability detection, query command for ad-hoc exploration, and ci command with SARIF/JSON output support. Integrates dataflow executor with pattern-based source-to-sink matching for intra-procedural taint analysis.
1 parent 3fa0b9c commit 35f3cf1

File tree

15 files changed

+2228
-244
lines changed

15 files changed

+2228
-244
lines changed

python-dsl/LICENSE

Lines changed: 661 additions & 0 deletions
Large diffs are not rendered by default.

python-dsl/MANIFEST.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
include LICENSE
2+
include README.md
3+
include pyproject.toml
4+
recursive-include codepathfinder *.py
5+
recursive-exclude tests *
6+
recursive-exclude htmlcov *
7+
recursive-exclude .pytest_cache *
8+
recursive-exclude .mypy_cache *
9+
recursive-exclude .ruff_cache *
10+
global-exclude *.pyc
11+
global-exclude __pycache__

python-dsl/README.md

Lines changed: 29 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -1,210 +1,50 @@
11
# Code-Pathfinder Python DSL
22

3-
Python DSL for defining security patterns in code-pathfinder.
3+
Python DSL for defining security patterns in Code Pathfinder - an open-source security suite combining structural code analysis with AI-powered vulnerability detection.
4+
5+
**Project Goals:**
6+
- Real-time IDE integration bringing security insights directly into your editor
7+
- AI-assisted analysis leveraging LLMs to understand context and identify vulnerabilities
8+
- Unified workflow coverage from local development to CI/CD pipelines
9+
- Flexible reporting supporting DefectDojo, GitHub Advanced Security, SARIF, and other platforms
10+
11+
**Documentation**: https://codepathfinder.dev/
412

513
## Installation
614

715
```bash
816
pip install codepathfinder
917
```
1018

11-
## Quick Start
12-
13-
```python
14-
from codepathfinder import rule, calls, variable
15-
16-
@rule(id="code-injection", severity="critical", cwe="CWE-94")
17-
def detect_eval():
18-
"""Detects dangerous code execution via eval/exec"""
19-
return calls("eval", "exec")
20-
21-
@rule(id="user-input", severity="high")
22-
def detect_user_input():
23-
"""Detects user input variables"""
24-
return variable("user_input")
25-
```
26-
27-
## Core Matchers
28-
29-
### `calls(*patterns)`
30-
31-
Matches function/method calls.
19+
## Quick Example
3220

3321
```python
34-
from codepathfinder import calls
35-
36-
# Exact match
37-
calls("eval")
38-
39-
# Multiple patterns
40-
calls("eval", "exec", "compile")
41-
42-
# Wildcard patterns
43-
calls("request.*") # Matches request.GET, request.POST, etc.
44-
calls("*.execute") # Matches cursor.execute, conn.execute, etc.
45-
```
46-
47-
### `variable(pattern)`
48-
49-
Matches variable references.
50-
51-
```python
52-
from codepathfinder import variable
53-
54-
# Exact match
55-
variable("user_input")
56-
57-
# Wildcard patterns
58-
variable("user_*") # Matches user_input, user_data, etc.
59-
variable("*_id") # Matches user_id, post_id, etc.
60-
```
61-
62-
## Dataflow Analysis
63-
64-
### `flows(from_sources, to_sinks, sanitized_by=None, propagates_through=None, scope="global")`
65-
66-
Tracks tainted data flow from sources to sinks for OWASP Top 10 vulnerability detection.
67-
68-
```python
69-
from codepathfinder import flows, calls, propagates
70-
71-
# SQL Injection
72-
flows(
73-
from_sources=calls("request.GET", "request.POST"),
74-
to_sinks=calls("execute", "executemany"),
75-
sanitized_by=calls("quote_sql"),
76-
propagates_through=[
77-
propagates.assignment(),
78-
propagates.function_args(),
79-
],
80-
scope="global"
81-
)
82-
83-
# Command Injection
84-
flows(
85-
from_sources=calls("request.POST"),
86-
to_sinks=calls("os.system", "subprocess.call"),
87-
sanitized_by=calls("shlex.quote"),
88-
propagates_through=[
89-
propagates.assignment(),
90-
propagates.function_args(),
91-
propagates.function_returns(),
92-
]
93-
)
94-
95-
# Path Traversal
96-
flows(
97-
from_sources=calls("request.GET"),
98-
to_sinks=calls("open", "os.path.join"),
99-
sanitized_by=calls("os.path.abspath"),
100-
propagates_through=[propagates.assignment()],
101-
scope="local"
102-
)
103-
```
22+
from codepathfinder import rule, flows, calls
23+
from codepathfinder.presets import PropagationPresets
10424

105-
**Parameters:**
106-
- `from_sources`: Source matcher(s) where taint originates (e.g., user input)
107-
- `to_sinks`: Sink matcher(s) for dangerous functions
108-
- `sanitized_by` (optional): Sanitizer matcher(s) that neutralize taint
109-
- `propagates_through` (optional): List of propagation primitives (EXPLICIT!)
110-
- `scope`: `"local"` (intra-procedural) or `"global"` (inter-procedural, default)
111-
112-
### Propagation Primitives
113-
114-
Propagation primitives define HOW taint flows through code:
115-
116-
```python
117-
from codepathfinder import propagates
118-
119-
# Phase 1 (Available Now):
120-
propagates.assignment() # x = tainted
121-
propagates.function_args() # func(tainted)
122-
propagates.function_returns() # return tainted
123-
```
124-
125-
**Important:** Propagation is EXPLICIT - you must specify which primitives to enable. No defaults are applied.
126-
127-
## Rule Decorator
128-
129-
The `@rule` decorator marks functions as security rules with metadata.
130-
131-
```python
132-
from codepathfinder import rule, calls
133-
134-
@rule(
135-
id="sqli-001",
136-
severity="critical",
137-
cwe="CWE-89",
138-
owasp="A03:2021"
139-
)
25+
@rule(id="sql-injection", severity="critical", cwe="CWE-89")
14026
def detect_sql_injection():
14127
"""Detects SQL injection vulnerabilities"""
142-
return calls("execute", "executemany", "raw")
143-
```
144-
145-
**Parameters:**
146-
- `id` (str): Unique rule identifier
147-
- `severity` (str): `critical` | `high` | `medium` | `low`
148-
- `cwe` (str, optional): CWE identifier (e.g., "CWE-89")
149-
- `owasp` (str, optional): OWASP category (e.g., "A03:2021")
150-
151-
The function docstring becomes the rule description.
152-
153-
## JSON IR Output
154-
155-
Rules serialize to JSON Intermediate Representation (IR) for the Go executor:
156-
157-
```python
158-
from codepathfinder import rule, calls
159-
import json
160-
161-
@rule(id="test", severity="high")
162-
def my_rule():
163-
return calls("eval")
164-
165-
# Serialize to JSON IR
166-
ir = my_rule.execute()
167-
print(json.dumps(ir, indent=2))
28+
return flows(
29+
from_sources=calls("request.GET", "request.POST"),
30+
to_sinks=calls("execute", "executemany"),
31+
sanitized_by=calls("quote_sql"),
32+
propagates_through=PropagationPresets.standard(),
33+
scope="global"
34+
)
16835
```
16936

170-
Output:
171-
```json
172-
{
173-
"rule": {
174-
"id": "test",
175-
"name": "my_rule",
176-
"severity": "high",
177-
"cwe": null,
178-
"owasp": null,
179-
"description": ""
180-
},
181-
"matcher": {
182-
"type": "call_matcher",
183-
"patterns": ["eval"],
184-
"wildcard": false,
185-
"match_mode": "any"
186-
}
187-
}
188-
```
189-
190-
## Development
191-
192-
```bash
193-
# Install with dev dependencies
194-
pip install -e ".[dev]"
195-
196-
# Run tests
197-
pytest
37+
## Features
19838

199-
# Format code
200-
black codepathfinder/ tests/
39+
- **Matchers**: `calls()`, `variable()` for pattern matching
40+
- **Dataflow Analysis**: `flows()` for source-to-sink taint tracking
41+
- **Propagation**: Explicit propagation primitives (assignment, function args, returns)
42+
- **Logic Operators**: `And()`, `Or()`, `Not()` for complex rules
43+
- **JSON IR**: Serializes to JSON for Go executor integration
20144

202-
# Lint
203-
ruff check codepathfinder/ tests/
45+
## Documentation
20446

205-
# Type check
206-
mypy codepathfinder/
207-
```
47+
For detailed documentation, visit https://codepathfinder.dev/
20848

20949
## Requirements
21050

@@ -213,4 +53,4 @@ mypy codepathfinder/
21353

21454
## License
21555

216-
MIT
56+
AGPL-3.0 - GNU Affero General Public License v3

python-dsl/pyproject.toml

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,30 @@ version = "1.0.0"
88
description = "Python DSL for code-pathfinder security patterns"
99
readme = "README.md"
1010
requires-python = ">=3.8"
11-
license = {text = "MIT"}
11+
license = {text = "AGPL-3.0"}
12+
authors = [{name = "code-pathfinder contributors"}]
13+
classifiers = [
14+
"Development Status :: 4 - Beta",
15+
"Intended Audience :: Developers",
16+
"License :: OSI Approved :: GNU Affero General Public License v3",
17+
"Programming Language :: Python :: 3",
18+
"Programming Language :: Python :: 3.8",
19+
"Programming Language :: Python :: 3.9",
20+
"Programming Language :: Python :: 3.10",
21+
"Programming Language :: Python :: 3.11",
22+
"Programming Language :: Python :: 3.12",
23+
"Topic :: Security",
24+
"Topic :: Software Development :: Testing",
25+
]
26+
27+
[project.optional-dependencies]
28+
dev = [
29+
"pytest>=7.0.0",
30+
"pytest-cov>=4.0.0",
31+
"black>=23.0.0",
32+
"mypy>=1.0.0",
33+
"ruff>=0.1.0",
34+
]
1235

1336
[tool.pytest.ini_options]
1437
testpaths = ["tests"]

python-dsl/setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
url="https://github.com/shivasurya/code-pathfinder",
2626
packages=find_packages(exclude=["tests", "tests.*"]),
2727
python_requires=">=3.8",
28+
license="AGPL-3.0",
2829
install_requires=[
2930
# No external dependencies (stdlib only!)
3031
],
@@ -40,7 +41,7 @@
4041
classifiers=[
4142
"Development Status :: 4 - Beta",
4243
"Intended Audience :: Developers",
43-
"License :: OSI Approved :: MIT License",
44+
"License :: OSI Approved :: GNU Affero General Public License v3",
4445
"Programming Language :: Python :: 3",
4546
"Programming Language :: Python :: 3.8",
4647
"Programming Language :: Python :: 3.9",

0 commit comments

Comments
 (0)