sorx 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sorx-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 _unkn?wn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
sorx-0.1.0/MANIFEST.in ADDED
@@ -0,0 +1 @@
1
+ recursive-include src/sorx *.yaml
sorx-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.4
2
+ Name: sorx
3
+ Version: 0.1.0
4
+ Summary: A tool for analyzing CORS headers
5
+ Description-Content-Type: text/markdown
6
+ License-File: LICENSE
7
+ Requires-Dist: PyYAML>=6.0
8
+ Requires-Dist: requests>=2.32
9
+ Requires-Dist: colorama>=0.4.6
10
+ Dynamic: license-file
11
+
12
+ # sorx
13
+
14
+ > A lightweight CORS security analyzer for bug bounty hunters.
15
+
16
+ `sorx` is a CLI tool for analyzing CORS configurations and detecting potentially security-relevant misconfigurations with a focus on **low noise and useful findings**.
17
+
18
+ > [!NOTE]
19
+ > **sorx is currently under active development.**
20
+ >
21
+ > The project is not ready for use yet. The main executable/CLI is not available at this time, and functionality is still being implemented.
22
+
23
+ ## Features
24
+
25
+ - CORS misconfiguration detection
26
+ - Active origin fuzzing
27
+ - Credential & origin reflection checks
28
+ - Sensitive header analysis
29
+ - HTTP method analysis
30
+ - CORS combination checks
31
+ - Configurable timeout, rate limit & threads
32
+ - JSON output
33
+ - Low-noise findings
34
+
35
+ ## Why sorx?
36
+
37
+ - **CLI-first** — Designed to fit naturally into recon and bug bounty pipelines.
38
+ - **Free & open source** — Free to use, inspect, modify, and contribute to.
39
+ - **Actively developed** — Continuously improved with new checks, payloads, and features.
40
+ - **Low noise** — Focuses on security-relevant CORS behavior instead of reporting every configuration.
41
+ - **Automation-friendly** — Supports JSON output and configurable threads, rate limits, and timeouts.
42
+ - **Lightweight** — Simple setup with minimal dependencies.
43
+ - **Built for hunters and testers** — Designed around practical CORS testing workflows rather than generic HTTP scanning.
44
+
45
+ ## Installation
46
+
47
+ ### pip
48
+
49
+ Install:
50
+
51
+ ```
52
+ pip install sorx
53
+ ```
54
+
55
+ Update:
56
+
57
+ ```
58
+ pip install -U sorx
59
+ ```
60
+
61
+ ### pipx
62
+
63
+ Install:
64
+
65
+ ```
66
+ pipx install sorx
67
+ ```
68
+
69
+ Update:
70
+
71
+ ```
72
+ pipx upgrade sorx
73
+ ```
74
+
75
+ ### From Github
76
+
77
+ Install directly from GitHub:
78
+
79
+ ```
80
+ pip install git+https://github.com/Pupsix/sorx.git
81
+ ```
82
+
83
+ Or with `pipx`:
84
+
85
+ ```
86
+ pipx install git+https://github.com/Pupsix/sorx.git
87
+ ```
88
+
89
+ ### From Source
90
+
91
+ Clone the repository:
92
+
93
+ ```
94
+ git clone https://github.com/Pupsix/sorx.git
95
+ cd sorx
96
+ ```
97
+
98
+ Create a virtual environment:
99
+
100
+ ```
101
+ python3 -m venv .venv
102
+ source .venv/bin/activate
103
+ ```
104
+
105
+ Install in editable mode:
106
+
107
+ ```
108
+ pip install -e .
109
+ ```
110
+
111
+ The editable installation allows changes to the source code to be reflected immediately without reinstalling the package.
112
+
113
+ > **Recommended:** Use `pip` or `pipx` for installation.
114
+ > Installing from source is intended for development.
115
+
116
+ ## Usage
117
+
118
+ Basic scan:
119
+
120
+ ```
121
+ sorx -u https://example.com
122
+ ```
123
+
124
+ Enable active CORS fuzzing:
125
+
126
+ ```
127
+ sorx -u https://example.com -a
128
+ ```
129
+
130
+ Select testing mode:
131
+
132
+ ```
133
+ sorx -u https://example.com -m quick
134
+ ```
135
+
136
+ ```
137
+ sorx -u https://example.com -m normal
138
+ ```
139
+
140
+ ```
141
+ sorx -u https://example.com -m deep
142
+ ```
143
+
144
+ For all available options:
145
+
146
+ ```
147
+ sorx --help
148
+ ```
149
+
150
+ ## Responsible Use
151
+
152
+ `sorx` is intended for authorized security testing, including:
153
+
154
+ - Bug bounty programs
155
+ - Penetration testing
156
+ - Security research
157
+ - Applications you own
158
+
159
+ Only test targets where you have permission to perform security testing.
160
+
161
+ Do not use active fuzzing against unauthorized systems.
162
+
163
+ ## Status
164
+
165
+ `sorx` is currently under development.
166
+
167
+ The project focuses on useful findings rather than the number of checks. Some CORS configurations may be unusual without being vulnerabilities, so sorx attempts to prioritize security-relevant behavior and reduce unnecessary noise.
168
+
169
+ ## License
170
+
171
+ MIT License
sorx-0.1.0/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # sorx
2
+
3
+ > A lightweight CORS security analyzer for bug bounty hunters.
4
+
5
+ `sorx` is a CLI tool for analyzing CORS configurations and detecting potentially security-relevant misconfigurations with a focus on **low noise and useful findings**.
6
+
7
+ > [!NOTE]
8
+ > **sorx is currently under active development.**
9
+ >
10
+ > The project is not ready for use yet. The main executable/CLI is not available at this time, and functionality is still being implemented.
11
+
12
+ ## Features
13
+
14
+ - CORS misconfiguration detection
15
+ - Active origin fuzzing
16
+ - Credential & origin reflection checks
17
+ - Sensitive header analysis
18
+ - HTTP method analysis
19
+ - CORS combination checks
20
+ - Configurable timeout, rate limit & threads
21
+ - JSON output
22
+ - Low-noise findings
23
+
24
+ ## Why sorx?
25
+
26
+ - **CLI-first** — Designed to fit naturally into recon and bug bounty pipelines.
27
+ - **Free & open source** — Free to use, inspect, modify, and contribute to.
28
+ - **Actively developed** — Continuously improved with new checks, payloads, and features.
29
+ - **Low noise** — Focuses on security-relevant CORS behavior instead of reporting every configuration.
30
+ - **Automation-friendly** — Supports JSON output and configurable threads, rate limits, and timeouts.
31
+ - **Lightweight** — Simple setup with minimal dependencies.
32
+ - **Built for hunters and testers** — Designed around practical CORS testing workflows rather than generic HTTP scanning.
33
+
34
+ ## Installation
35
+
36
+ ### pip
37
+
38
+ Install:
39
+
40
+ ```
41
+ pip install sorx
42
+ ```
43
+
44
+ Update:
45
+
46
+ ```
47
+ pip install -U sorx
48
+ ```
49
+
50
+ ### pipx
51
+
52
+ Install:
53
+
54
+ ```
55
+ pipx install sorx
56
+ ```
57
+
58
+ Update:
59
+
60
+ ```
61
+ pipx upgrade sorx
62
+ ```
63
+
64
+ ### From Github
65
+
66
+ Install directly from GitHub:
67
+
68
+ ```
69
+ pip install git+https://github.com/Pupsix/sorx.git
70
+ ```
71
+
72
+ Or with `pipx`:
73
+
74
+ ```
75
+ pipx install git+https://github.com/Pupsix/sorx.git
76
+ ```
77
+
78
+ ### From Source
79
+
80
+ Clone the repository:
81
+
82
+ ```
83
+ git clone https://github.com/Pupsix/sorx.git
84
+ cd sorx
85
+ ```
86
+
87
+ Create a virtual environment:
88
+
89
+ ```
90
+ python3 -m venv .venv
91
+ source .venv/bin/activate
92
+ ```
93
+
94
+ Install in editable mode:
95
+
96
+ ```
97
+ pip install -e .
98
+ ```
99
+
100
+ The editable installation allows changes to the source code to be reflected immediately without reinstalling the package.
101
+
102
+ > **Recommended:** Use `pip` or `pipx` for installation.
103
+ > Installing from source is intended for development.
104
+
105
+ ## Usage
106
+
107
+ Basic scan:
108
+
109
+ ```
110
+ sorx -u https://example.com
111
+ ```
112
+
113
+ Enable active CORS fuzzing:
114
+
115
+ ```
116
+ sorx -u https://example.com -a
117
+ ```
118
+
119
+ Select testing mode:
120
+
121
+ ```
122
+ sorx -u https://example.com -m quick
123
+ ```
124
+
125
+ ```
126
+ sorx -u https://example.com -m normal
127
+ ```
128
+
129
+ ```
130
+ sorx -u https://example.com -m deep
131
+ ```
132
+
133
+ For all available options:
134
+
135
+ ```
136
+ sorx --help
137
+ ```
138
+
139
+ ## Responsible Use
140
+
141
+ `sorx` is intended for authorized security testing, including:
142
+
143
+ - Bug bounty programs
144
+ - Penetration testing
145
+ - Security research
146
+ - Applications you own
147
+
148
+ Only test targets where you have permission to perform security testing.
149
+
150
+ Do not use active fuzzing against unauthorized systems.
151
+
152
+ ## Status
153
+
154
+ `sorx` is currently under development.
155
+
156
+ The project focuses on useful findings rather than the number of checks. Some CORS configurations may be unusual without being vulnerabilities, so sorx attempts to prioritize security-relevant behavior and reduce unnecessary noise.
157
+
158
+ ## License
159
+
160
+ MIT License
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sorx"
7
+ version = "0.1.0"
8
+ description = "A tool for analyzing CORS headers"
9
+ readme = "README.md"
10
+ dependencies = [
11
+ "PyYAML>=6.0",
12
+ "requests>=2.32",
13
+ "colorama>=0.4.6",
14
+ ]
15
+
16
+ [tool.setuptools.packages.find]
17
+ where = ["src"]
18
+
19
+ [project.scripts]
20
+ sorx = "sorx.main:main"
sorx-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ from importlib.metadata import version
2
+
3
+ __version__ = version("sorx")
@@ -0,0 +1,147 @@
1
+ import time
2
+
3
+ from sorx.checks.cors_analyze import analyze
4
+ from sorx.core.display import header
5
+ from sorx.core.requester import run as requester_run
6
+ from sorx.data.loader.payload import load_payload
7
+
8
+
9
+ class Stat:
10
+ def __init__(self, targets, mode, threads, config):
11
+ self.targets_list, self.targets = list(targets), len(targets)
12
+ self.mode, self.threads = mode, threads
13
+ self.header = config.get("headers", {})
14
+ self.scanned = 0
15
+ self.findings = {url: [] for url in targets}
16
+ self.errors = {url: [] for url in targets}
17
+ self.start_time = time.time()
18
+ self.error = self.request = 0
19
+ self.elapsed = "00:00"
20
+ self.output = config.get("output") or "None"
21
+
22
+
23
+ def create_job(url, method="GET", headers=None, data=None, timeout=10, origin=None):
24
+ return {
25
+ "url": url,
26
+ "method": method,
27
+ "headers": headers or {},
28
+ "data": data,
29
+ "timeout": timeout,
30
+ "origin": origin or "",
31
+ }
32
+
33
+
34
+ def get_payloads(name, mode):
35
+ payloads = load_payload(name).get(name, {})
36
+ priority_map = {
37
+ "quick": ["high_priority"],
38
+ "normal": ["high_priority", "medium_priority"],
39
+ "deep": ["high_priority", "medium_priority", "low_priority"],
40
+ }
41
+ result = []
42
+ for priority in priority_map.get(mode, []):
43
+ result.extend(payloads.get(priority, []))
44
+ return result
45
+
46
+
47
+ def passive(url, config):
48
+ return [
49
+ create_job(
50
+ url=url,
51
+ method=config.get("method", "GET"),
52
+ headers=config.get("headers", {}),
53
+ data=config.get("data"),
54
+ timeout=config.get("timeout", 10),
55
+ )
56
+ ]
57
+
58
+
59
+ def active(url, config):
60
+ mode, timeout, base_headers = config.get("mode"), config.get("timeout", 10), config.get("headers", {})
61
+ jobs = []
62
+
63
+ # Origin fuzzing
64
+ for origin in get_payloads("origin", mode):
65
+ jobs.append(create_job(url=url, method="GET", headers={**base_headers, "Origin": origin}, timeout=timeout, origin=origin))
66
+
67
+ # Preflight
68
+ jobs.append(
69
+ create_job(
70
+ url=url,
71
+ method="OPTIONS",
72
+ headers={
73
+ **base_headers,
74
+ "Origin": "https://attacker.example",
75
+ "Access-Control-Request-Method": "POST",
76
+ "Access-Control-Request-Headers": "Authorization",
77
+ },
78
+ timeout=timeout,
79
+ origin="https://attacker.example",
80
+ )
81
+ )
82
+
83
+ return jobs
84
+
85
+
86
+ def update_elapsed(stat):
87
+ elapsed = time.time() - stat.start_time
88
+ stat.elapsed = f"{int(elapsed // 60):02d}:{int(elapsed % 60):02d}"
89
+
90
+
91
+ def analyze_results(stat, results):
92
+ for result in results:
93
+ task = result.get("task")
94
+ if not task:
95
+ continue
96
+
97
+ target_url = task.get("url")
98
+ if target_url not in stat.findings:
99
+ continue
100
+
101
+ error = result.get("error")
102
+ if error is not None:
103
+ stat.error += 1
104
+ if error not in stat.errors[target_url]:
105
+ stat.errors[target_url].append(error)
106
+ continue
107
+
108
+ response = result.get("response")
109
+ if response is None:
110
+ continue
111
+
112
+ for finding in analyze(response=response, task=task):
113
+ if finding not in stat.findings[target_url]:
114
+ stat.findings[target_url].append(finding)
115
+
116
+
117
+ def run(urls, config, on_target_done=None):
118
+ mode = config.get("mode")
119
+ mode_name = "passive" if mode is None else mode
120
+ workers = config.get("workers", 10)
121
+
122
+ urls = [urls] if isinstance(urls, str) else list(urls)
123
+ stat = Stat(targets=urls, mode=mode_name, threads=workers, config=config)
124
+
125
+ header(stat)
126
+
127
+ for url in urls:
128
+ # Build jobs
129
+ jobs = passive(url=url, config=config) if mode is None else active(url=url, config=config)
130
+
131
+ # Count requests
132
+ stat.request += len(jobs)
133
+
134
+ # Send requests & Analyze responses
135
+ results = requester_run(jobs=jobs, workers=workers)
136
+ analyze_results(stat=stat, results=results)
137
+
138
+ # Target finished
139
+ stat.scanned += 1
140
+ update_elapsed(stat)
141
+
142
+ # Tell caller that this target is finished
143
+ if on_target_done:
144
+ on_target_done(url, stat.findings[url], stat.errors[url])
145
+
146
+ update_elapsed(stat)
147
+ return stat
@@ -0,0 +1,80 @@
1
+ from sorx.data.loader.template import load_template
2
+
3
+
4
+ def analyze(response, task):
5
+ findings = []
6
+
7
+ # Load templates
8
+ header_template = load_template("sensitive_headers")
9
+ method_template = load_template("sensitive_method")
10
+
11
+ # Response headers & normalization
12
+ headers = response.headers
13
+ allow_origin = headers.get("Access-Control-Allow-Origin", "").strip().lower()
14
+ allow_credentials = headers.get("Access-Control-Allow-Credentials", "").strip().lower()
15
+ attacker_origin = (task.get("origin") or "").strip().lower()
16
+
17
+ # Parse headers and methods into sets
18
+ parse_csv = lambda val, case_fn: {case_fn(x.strip()) for x in val.split(",") if x.strip()} if val else set()
19
+ allowed_headers = parse_csv(headers.get("Access-Control-Allow-Headers", ""), str.lower)
20
+ allowed_methods = parse_csv(headers.get("Access-Control-Allow-Methods", ""), str.upper)
21
+ exposed_headers = parse_csv(headers.get("Access-Control-Expose-Headers", ""), str.lower)
22
+
23
+ # Sensitive lookup sets
24
+ sensitive_request_headers = {h.lower() for h in header_template["sensitive_request_headers"]}
25
+ sensitive_response_headers = {h.lower() for h in header_template["sensitive_response_headers"]}
26
+ sensitive_methods = {m.upper() for m in method_template["sensitive_methods"]}
27
+
28
+ # Basic check flags
29
+ wildcard_origin = allow_origin == "*"
30
+ origin_reflection = bool(attacker_origin and allow_origin == attacker_origin)
31
+ null_origin = allow_origin == "null"
32
+ credentials = allow_credentials == "true"
33
+
34
+ # Rule checks
35
+ if wildcard_origin:
36
+ findings.append(("CORS-001", "Wildcard origin"))
37
+
38
+ if origin_reflection:
39
+ findings.append(
40
+ ("CORS-101", "Attacker origin reflected with credentials")
41
+ if credentials
42
+ else ("CORS-100", "Attacker origin reflected")
43
+ )
44
+
45
+ if null_origin:
46
+ findings.append(
47
+ ("CORS-200", "Null origin with credentials")
48
+ if credentials
49
+ else ("CORS-201", "Null origin allowed")
50
+ )
51
+
52
+ # Header & Method checks
53
+ found_sensitive_request_header = bool(allowed_headers & sensitive_request_headers)
54
+ if found_sensitive_request_header:
55
+ findings.append(("CORS-300", "Sensitive request header allowed"))
56
+
57
+ if "*" in allowed_headers:
58
+ findings.append(("CORS-301", "Wildcard request headers"))
59
+
60
+ if "*" in allowed_methods:
61
+ findings.append(("CORS-302", "Wildcard request methods"))
62
+
63
+ found_sensitive_response_header = bool(exposed_headers & sensitive_response_headers)
64
+ if found_sensitive_response_header:
65
+ findings.append(("CORS-400", "Sensitive response header exposed"))
66
+
67
+ found_sensitive_method = bool(allowed_methods & sensitive_methods)
68
+
69
+ # Advanced correlation rules
70
+ if origin_reflection and credentials:
71
+ if "authorization" in allowed_headers:
72
+ findings.append(("CORS-900", "Origin reflection with credentials and Authorization"))
73
+
74
+ if found_sensitive_request_header or found_sensitive_response_header:
75
+ findings.append(("CORS-901", "Origin reflection with credentials and sensitive headers"))
76
+
77
+ if "*" in allowed_methods or found_sensitive_method:
78
+ findings.append(("CORS-902", "Origin reflection with credentials and broad methods"))
79
+
80
+ return findings