hackscan 0.1.0__py3-none-any.whl
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.
- hackscan/__init__.py +3 -0
- hackscan/analyzers/__init__.py +1 -0
- hackscan/analyzers/ast_pass.py +154 -0
- hackscan/analyzers/suppressions.py +63 -0
- hackscan/analyzers/taint_pass.py +808 -0
- hackscan/cli.py +326 -0
- hackscan/config.py +184 -0
- hackscan/core/__init__.py +1 -0
- hackscan/core/dedupe.py +147 -0
- hackscan/core/fingerprint.py +76 -0
- hackscan/core/models.py +270 -0
- hackscan/core/pipeline.py +164 -0
- hackscan/core/redact.py +84 -0
- hackscan/core/taxonomy.py +111 -0
- hackscan/importers/__init__.py +1 -0
- hackscan/importers/common.py +198 -0
- hackscan/importers/gitleaks.py +104 -0
- hackscan/importers/runner.py +161 -0
- hackscan/importers/sarif.py +164 -0
- hackscan/plugins/__init__.py +5 -0
- hackscan/plugins/base.py +261 -0
- hackscan/plugins/loader.py +98 -0
- hackscan/plugins/rules/__init__.py +1 -0
- hackscan/plugins/rules/cmdi.py +80 -0
- hackscan/plugins/rules/codei.py +50 -0
- hackscan/plugins/rules/sqli.py +127 -0
- hackscan/plugins/rules/weak_crypto.py +53 -0
- hackscan/plugins/scopes.py +263 -0
- hackscan/sarif/__init__.py +1 -0
- hackscan/sarif/generator.py +205 -0
- hackscan/taint/__init__.py +1 -0
- hackscan/taint/sanitizers.py +37 -0
- hackscan/taint/sources.py +99 -0
- hackscan-0.1.0.dist-info/METADATA +181 -0
- hackscan-0.1.0.dist-info/RECORD +38 -0
- hackscan-0.1.0.dist-info/WHEEL +4 -0
- hackscan-0.1.0.dist-info/entry_points.txt +2 -0
- hackscan-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Sanitizers: calls whose result is safe for some (or all) injection classes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from hackscan.core.taxonomy import CMDI, SQLI, TAINT_CLASSES
|
|
6
|
+
|
|
7
|
+
ALL = TAINT_CLASSES
|
|
8
|
+
|
|
9
|
+
# Fully-qualified call name -> vuln classes the result is safe for.
|
|
10
|
+
SANITIZERS: dict[str, frozenset[str]] = {
|
|
11
|
+
# Numeric / boolean / identifier conversions cannot carry injection payloads.
|
|
12
|
+
"int": ALL,
|
|
13
|
+
"float": ALL,
|
|
14
|
+
"bool": ALL,
|
|
15
|
+
"abs": ALL,
|
|
16
|
+
"len": ALL,
|
|
17
|
+
"round": ALL,
|
|
18
|
+
"builtins.int": ALL,
|
|
19
|
+
"builtins.float": ALL,
|
|
20
|
+
"uuid.UUID": ALL,
|
|
21
|
+
"decimal.Decimal": ALL,
|
|
22
|
+
# Shell quoting. Context-sensitive: see QUOTING_SANITIZERS.
|
|
23
|
+
"shlex.quote": frozenset({CMDI}),
|
|
24
|
+
"shlex.join": frozenset({CMDI}),
|
|
25
|
+
"pipes.quote": frozenset({CMDI}),
|
|
26
|
+
# SQL identifier/literal quoting helpers.
|
|
27
|
+
"psycopg2.sql.Identifier": frozenset({SQLI}),
|
|
28
|
+
"psycopg2.sql.Literal": frozenset({SQLI}),
|
|
29
|
+
"psycopg.sql.Identifier": frozenset({SQLI}),
|
|
30
|
+
"psycopg.sql.Literal": frozenset({SQLI}),
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Sanitizers whose safety depends on where the result is placed: a shell-quoted value
|
|
34
|
+
# embedded inside another quote context (`'echo "' + shlex.quote(x) + '"'`) is unsafe.
|
|
35
|
+
# Note: `ast.literal_eval` is deliberately absent: it can return a string, which is
|
|
36
|
+
# still dangerous when passed on to eval/exec.
|
|
37
|
+
QUOTING_SANITIZERS = frozenset({"shlex.quote", "shlex.join", "pipes.quote"})
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Untrusted input sources: web frameworks, CLI and stdin.
|
|
2
|
+
|
|
3
|
+
Sources are matched three ways:
|
|
4
|
+
1. Resolved dotted names (`flask.request.args`, `sys.argv`, builtin `input`).
|
|
5
|
+
2. Request-object parameters: a parameter named `request`/`req` (Django, DRF, Starlette,
|
|
6
|
+
FastAPI `Request`) whose request-data attributes are read.
|
|
7
|
+
3. Route handler parameters: every parameter of a function decorated with a routing
|
|
8
|
+
decorator (`@app.route`, `@app.get`, `@router.post`, ...) is client-controlled
|
|
9
|
+
(Flask path variables, FastAPI path/query/body parameters).
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import ast
|
|
15
|
+
|
|
16
|
+
# Attributes of `flask.request` that carry client data.
|
|
17
|
+
FLASK_REQUEST_ATTRS = frozenset(
|
|
18
|
+
{
|
|
19
|
+
"args",
|
|
20
|
+
"form",
|
|
21
|
+
"values",
|
|
22
|
+
"json",
|
|
23
|
+
"data",
|
|
24
|
+
"cookies",
|
|
25
|
+
"headers",
|
|
26
|
+
"files",
|
|
27
|
+
"get_json",
|
|
28
|
+
"get_data",
|
|
29
|
+
"view_args",
|
|
30
|
+
"path",
|
|
31
|
+
"full_path",
|
|
32
|
+
"url",
|
|
33
|
+
"query_string",
|
|
34
|
+
"stream",
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Attributes of a request parameter (Django/DRF/Starlette/FastAPI) that carry client data.
|
|
39
|
+
REQUEST_PARAM_ATTRS = frozenset(
|
|
40
|
+
{
|
|
41
|
+
# Django
|
|
42
|
+
"GET",
|
|
43
|
+
"POST",
|
|
44
|
+
"body",
|
|
45
|
+
"COOKIES",
|
|
46
|
+
"META",
|
|
47
|
+
"FILES",
|
|
48
|
+
"headers",
|
|
49
|
+
"path",
|
|
50
|
+
"path_info",
|
|
51
|
+
# DRF
|
|
52
|
+
"data",
|
|
53
|
+
"query_params",
|
|
54
|
+
# Starlette / FastAPI
|
|
55
|
+
"path_params",
|
|
56
|
+
"cookies",
|
|
57
|
+
"json",
|
|
58
|
+
"form",
|
|
59
|
+
"url",
|
|
60
|
+
# Flask-style, when a request object is passed around
|
|
61
|
+
"args",
|
|
62
|
+
"values",
|
|
63
|
+
"get_json",
|
|
64
|
+
"get_data",
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
REQUEST_PARAM_NAMES = frozenset({"request", "req"})
|
|
68
|
+
|
|
69
|
+
# Fully-qualified names whose value (attribute) or return value (call) is untrusted.
|
|
70
|
+
SOURCE_NAMES = {
|
|
71
|
+
"sys.argv": "command-line arguments (sys.argv)",
|
|
72
|
+
"sys.stdin": "standard input (sys.stdin)",
|
|
73
|
+
"input": "user input (input())",
|
|
74
|
+
"builtins.input": "user input (input())",
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# Decorator method names that register an HTTP route handler.
|
|
78
|
+
ROUTE_DECORATORS = frozenset(
|
|
79
|
+
{"route", "get", "post", "put", "patch", "delete", "head", "options", "api_route", "websocket"}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def flask_request_source(resolved: str) -> str | None:
|
|
84
|
+
"""`flask.request.args` -> description, for any resolved dotted name."""
|
|
85
|
+
prefix = "flask.request."
|
|
86
|
+
if resolved.startswith(prefix):
|
|
87
|
+
attr = resolved[len(prefix) :].split(".", 1)[0]
|
|
88
|
+
if attr in FLASK_REQUEST_ATTRS:
|
|
89
|
+
return f"Flask request data (request.{attr})"
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def is_route_handler(func: ast.AST) -> bool:
|
|
94
|
+
"""Decorated with `@<obj>.route(...)`, `@<obj>.get(...)`, etc."""
|
|
95
|
+
for deco in getattr(func, "decorator_list", ()):
|
|
96
|
+
target = deco.func if isinstance(deco, ast.Call) else deco
|
|
97
|
+
if isinstance(target, ast.Attribute) and target.attr in ROUTE_DECORATORS:
|
|
98
|
+
return True
|
|
99
|
+
return False
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: hackscan
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SAST orchestrator: own AST + taint engine, imports Semgrep/Bandit/CodeQL/Gitleaks, dedupes, emits SARIF.
|
|
5
|
+
Project-URL: Source, https://github.com/kahledawad2019-netizen/hackscan
|
|
6
|
+
Project-URL: Issues, https://github.com/kahledawad2019-netizen/hackscan/issues
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: sarif,sast,security,static-analysis,taint-analysis,vulnerability-scanner
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Security
|
|
20
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: click>=8.1
|
|
23
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# HackScan
|
|
27
|
+
|
|
28
|
+
**A Python security scanner that verifies what it reports.** HackScan finds injection
|
|
29
|
+
sinks with its own AST engine, then runs a flow-sensitive taint analysis to decide, per
|
|
30
|
+
finding, whether untrusted input really reaches it. It can also ingest Semgrep, Bandit,
|
|
31
|
+
CodeQL and Gitleaks results, merge duplicates across tools, and emit one SARIF report.
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
$ hackscan scan app/
|
|
35
|
+
HIGH confirmed views.py:10:9 HS-SQLI-001 [100%]
|
|
36
|
+
SQL query is built with string formatting/concatenation.
|
|
37
|
+
| cursor.execute("SELECT * FROM sales WHERE year = " + year)
|
|
38
|
+
> Untrusted request data (`request.GET`) at line 8.
|
|
39
|
+
> Untrusted input reaches the sink.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Why another scanner?
|
|
43
|
+
|
|
44
|
+
| | HackScan |
|
|
45
|
+
|---|---|
|
|
46
|
+
| **Verdicts, not just matches** | Every injection candidate is **confirmed** (untrusted source reaches it, with a trace), **suppressed** (provably constant or sanitized on every path), or left as a **candidate** for review. |
|
|
47
|
+
| **Sound suppression** | A finding is only dismissed if *every* path is safe. Branches, loops (`break`/`continue`), `try`/`except`/`finally`, aliasing and mutation of lists/dicts, closures and `:=` are modeled. A differential fuzzer executes thousands of random programs to check that no dismissed sink ever receives attacker input. |
|
|
48
|
+
| **Framework-aware** | Sources: Flask `request.*`, Django/DRF/Starlette/FastAPI request objects (incl. `self.request`), route-handler parameters, `input()`, `sys.argv`. |
|
|
49
|
+
| **One report from many tools** | Imports Semgrep, Bandit, CodeQL (SARIF) and Gitleaks; deduplicates by vulnerability class and location, keeping every tool as provenance. |
|
|
50
|
+
| **CI-ready** | SARIF 2.1.0 (validated against the OASIS schema) for GitHub code scanning, `--fail-on` exit codes, stable fingerprints that survive code moves. |
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install hackscan # or: uv tool install hackscan / pipx install hackscan
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Python 3.10–3.13, any OS. No network access and no LLM needed.
|
|
59
|
+
|
|
60
|
+
## Usage
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
hackscan scan . # text report
|
|
64
|
+
hackscan scan . --format sarif -o hackscan.sarif # for GitHub code scanning
|
|
65
|
+
hackscan scan . --fail-on high # exit 1 on open high/critical findings
|
|
66
|
+
hackscan scan . --format json --show-suppressed # everything, machine-readable
|
|
67
|
+
hackscan scan . --with bandit,semgrep,gitleaks # also run these tools if installed
|
|
68
|
+
hackscan scan . --import codeql=results.sarif # merge a report you already have
|
|
69
|
+
hackscan rules # list rules
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
| Option | Meaning |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `--severity`, `--min-confidence` | Report filters. |
|
|
75
|
+
| `--fail-on SEV` | Exit 1 if an open (candidate/confirmed) finding is at least `SEV`. Suppressed findings never count. |
|
|
76
|
+
| `--ignore GLOB` | Skip paths (`tests/*`, `**/migrations/**`, `legacy`). `.venv`, `node_modules`, `build`, ... are always skipped. |
|
|
77
|
+
| `--with TOOLS` / `--import FMT=FILE` | Run external tools / import reports (`sarif`, `semgrep`, `bandit`, `codeql`, `gitleaks`). A missing or failing tool is a warning unless `--strict-tools`. |
|
|
78
|
+
| `-o FILE` | Write the report to `FILE`. Never overwrites anything except a previous HackScan report. |
|
|
79
|
+
| `--plugins DIR` | Load custom rules (see below). |
|
|
80
|
+
| `--allow-incomplete` | Do not exit 2 when some files cannot be analyzed (they are still listed). |
|
|
81
|
+
| `--no-taint` | Pattern matching only. |
|
|
82
|
+
| `--jobs N` | Worker processes (default: automatic). |
|
|
83
|
+
|
|
84
|
+
Exit codes: `0` OK, `1` `--fail-on` threshold reached, `2` usage/config/plugin error or
|
|
85
|
+
an **incomplete scan** (a file could not be parsed or read, or an `--import` report
|
|
86
|
+
could not be loaded; use `--allow-incomplete` to accept). A `--with` tool that is missing
|
|
87
|
+
or exits with an error is a warning, or exit `2` with `--strict-tools`. An incomplete scan is never reported as a pass, and SARIF marks it with
|
|
88
|
+
`executionSuccessful: false`.
|
|
89
|
+
|
|
90
|
+
### Configuration
|
|
91
|
+
|
|
92
|
+
`.hackscan.yml` files are discovered from the filesystem root down to the scanned
|
|
93
|
+
directory and merged (nearest wins; `ignore` lists accumulate). CLI options override them.
|
|
94
|
+
|
|
95
|
+
```yaml
|
|
96
|
+
ignore: [tests/*, "**/migrations/**"]
|
|
97
|
+
severity: medium
|
|
98
|
+
min-confidence: 40
|
|
99
|
+
fail-on: high
|
|
100
|
+
with: [bandit]
|
|
101
|
+
import:
|
|
102
|
+
codeql: codeql-results.sarif
|
|
103
|
+
plugins: security/rules
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Suppressing a finding
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
os.system(cmd) # hackscan: ignore[HS-CMDI-001]
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Suppressed findings stay in SARIF output (as `suppressions`) so they remain auditable;
|
|
113
|
+
use `--sarif-omit-suppressed` when uploading to GitHub, which does not honor them.
|
|
114
|
+
|
|
115
|
+
Secrets are never echoed: findings of class `secret` (from any tool) have generic
|
|
116
|
+
messages and redacted snippets, and values reported by Gitleaks are scrubbed from all
|
|
117
|
+
output, including warnings.
|
|
118
|
+
|
|
119
|
+
## Rules
|
|
120
|
+
|
|
121
|
+
| Rule | Detects | Severity |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `HS-SQLI-001` | Non-constant SQL reaching DB-API `execute*`, Django `raw`, SQLAlchemy `text`, pandas `read_sql` | high |
|
|
124
|
+
| `HS-CMDI-001` | Non-constant commands reaching `os.system`, `os.popen`, `subprocess.*(shell=True)`, ... | high |
|
|
125
|
+
| `HS-CODEI-001` | Non-constant input to `eval`, `exec`, `compile` | high |
|
|
126
|
+
| `HS-CRYPTO-001` | MD5/SHA-1 (unless `usedforsecurity=False`) | low |
|
|
127
|
+
|
|
128
|
+
Sanitizers recognized: numeric/UUID conversions (all classes), `psycopg` `sql.Identifier`
|
|
129
|
+
/`sql.Literal` (SQL). `shlex.quote` is POSIX-only, so quoted commands are kept as
|
|
130
|
+
low-confidence candidates rather than suppressed.
|
|
131
|
+
|
|
132
|
+
### Custom rules
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
# security/rules/pickle_rule.py
|
|
136
|
+
from hackscan.core.models import Severity
|
|
137
|
+
from hackscan.plugins import Match, RulePlugin
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class PickleLoads(RulePlugin):
|
|
141
|
+
rule_id = "ACME-PICKLE-001" # the HS- prefix is reserved
|
|
142
|
+
name = "pickle-loads"
|
|
143
|
+
description = "pickle.loads on untrusted data"
|
|
144
|
+
severity = Severity.HIGH
|
|
145
|
+
cwe = ("CWE-502",)
|
|
146
|
+
|
|
147
|
+
def check(self, node, ctx):
|
|
148
|
+
if "pickle.loads" in ctx.call_names(node):
|
|
149
|
+
yield Match(node, "pickle.loads call")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## GitHub Actions
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
- run: pipx install hackscan
|
|
156
|
+
- run: hackscan scan . --format sarif --sarif-omit-suppressed -o hackscan.sarif --fail-on high
|
|
157
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
158
|
+
if: always()
|
|
159
|
+
with:
|
|
160
|
+
sarif_file: hackscan.sarif
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Limitations
|
|
164
|
+
|
|
165
|
+
- Taint analysis is intra-procedural: values arriving through function parameters are
|
|
166
|
+
candidates, not confirmations (inter-procedural analysis is on the roadmap).
|
|
167
|
+
- Python only. Imported tools may cover other languages; their findings are passed through.
|
|
168
|
+
|
|
169
|
+
## Development
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
uv sync --group dev
|
|
173
|
+
uv run pytest
|
|
174
|
+
uv run ruff check . && uv run ruff format --check .
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
See [PROJECT.md](PROJECT.md) for the design, milestones and decision log.
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
MIT
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
hackscan/__init__.py,sha256=GcNLXUbJFNBS3K-SvHhkLUK9cOMWVGY1ZeZt48qjt2w,78
|
|
2
|
+
hackscan/cli.py,sha256=3UJJrJ6YHsTZsfve08xlgFecuU8FsV9mA3imd7pWcik,12878
|
|
3
|
+
hackscan/config.py,sha256=mzer8CtjwdxQutrtmMS14k66USLjxDXZzLzSSWRycBs,6547
|
|
4
|
+
hackscan/analyzers/__init__.py,sha256=elBA2v6nafQUQNdepIOzhnF1dfJNpdIM1r7_u7TYkII,23
|
|
5
|
+
hackscan/analyzers/ast_pass.py,sha256=z9m7zhJyILLNWOWn3kmNHy8yn6rwYjR-4kiBx79pWag,6056
|
|
6
|
+
hackscan/analyzers/suppressions.py,sha256=hcKBlK6729DZT3cFmW3p42RzFtvi3Nh93tneQjtkAKQ,2303
|
|
7
|
+
hackscan/analyzers/taint_pass.py,sha256=xxU39JD7m1hZu3mzj41SCd2warHMaFUzjh5_hzBfQlc,34350
|
|
8
|
+
hackscan/core/__init__.py,sha256=PCIydZsEkHbAAwx6huzlLKZIjZVwdN3zmYzzDGUiApo,60
|
|
9
|
+
hackscan/core/dedupe.py,sha256=Fs58QHoTUIqvhwTGDHWM_y8exDfQXJWXhE9k_tu7VCQ,5787
|
|
10
|
+
hackscan/core/fingerprint.py,sha256=dnzay8zrqXi7RZzJzE-J8a535Gf3HBwgFtLYD691wx8,2561
|
|
11
|
+
hackscan/core/models.py,sha256=Drv92BkGGP161f7eHrkYk3Bc0iYnJ6VNz5uW6T80f7I,9284
|
|
12
|
+
hackscan/core/pipeline.py,sha256=Okjh1IybZgjh86h7DBJ5GG78DZ2nNbre8myv5uIQfCo,6241
|
|
13
|
+
hackscan/core/redact.py,sha256=dJN7RC01yVP_1IrOHeJ0IzobNQJlBCSdQ2mVgeuGArg,3405
|
|
14
|
+
hackscan/core/taxonomy.py,sha256=ry_x7K3z9rh1AY5W7q7Fjib9OSMG2YYeAKEC9gEEwLs,3268
|
|
15
|
+
hackscan/importers/__init__.py,sha256=fuGmHD8qS_xDk57KLCkDO4fZLXHraaNnAtE3MdV5pb0,49
|
|
16
|
+
hackscan/importers/common.py,sha256=JE1BhKNTTHnJefadNMqUcjca01DwbhkUVad6s9qCZTg,7577
|
|
17
|
+
hackscan/importers/gitleaks.py,sha256=aWzi2zjHy1VCoVaB6QxruW0U2qzbl9MiVRgBd3z53tM,3789
|
|
18
|
+
hackscan/importers/runner.py,sha256=w66aWDa_lECGekNOsKDIzu1fzATJeuceY92IPIEUJ4A,5937
|
|
19
|
+
hackscan/importers/sarif.py,sha256=L0bvKQUqCxw3weEsLgNoRFXVU-xVzH0QGapPV_uJ5Vo,5931
|
|
20
|
+
hackscan/plugins/__init__.py,sha256=ftL30V67HM7IlVwdZ75Diajl6O0KlW896xQzuS6UsGM,197
|
|
21
|
+
hackscan/plugins/base.py,sha256=nmXhLmApn3iaHId8sovOUU5WjwBiVmc8rg5hufYjhTY,10198
|
|
22
|
+
hackscan/plugins/loader.py,sha256=cWS79msmrMV1SBqj8coIqj6UI3UCM7Hbn1WMy0V6uGU,3926
|
|
23
|
+
hackscan/plugins/scopes.py,sha256=4GDUAdxalzcq8pEuoXxu9ougMA_YMh0UYipzmUjvGBg,11484
|
|
24
|
+
hackscan/plugins/rules/__init__.py,sha256=QlFidHeq30_8JfoB4PMxjrGQfQGeYohdZQdQ3cMUTgw,32
|
|
25
|
+
hackscan/plugins/rules/cmdi.py,sha256=KtU0DZIxLHdyP7tc6_SVS2Q3F7y8Lf4MDLo9kYuO5jo,2420
|
|
26
|
+
hackscan/plugins/rules/codei.py,sha256=9uBSpWdU1l_eoOEWhU5jBCpJSjKb00HWT5WwYXDIciw,1503
|
|
27
|
+
hackscan/plugins/rules/sqli.py,sha256=7-5Ab-wKGf3E4Pl7OwwJfEP9q8NjlKli8P5tzergghA,4184
|
|
28
|
+
hackscan/plugins/rules/weak_crypto.py,sha256=Ikfbkf1iMXi4YG319FFwXjR_-n3M30KyP6YpyZIy1Ak,1952
|
|
29
|
+
hackscan/sarif/__init__.py,sha256=pvckjpJyukYgJmh_K2k8McH0xr5sVOSdQ2ExwnhHPXM,26
|
|
30
|
+
hackscan/sarif/generator.py,sha256=RadNx_1-dL6uDptfHQXSuIO1EjuBjm_WJbXC4n-PzVg,7898
|
|
31
|
+
hackscan/taint/__init__.py,sha256=LtqvgHY01Ya-lIis87zVxBbaz8OwGm-_SR6b8tz-YIg,44
|
|
32
|
+
hackscan/taint/sanitizers.py,sha256=Edqvr5UFyAFBKWilhxGgz2es2z8aXhjd37nGhtOPjNo,1396
|
|
33
|
+
hackscan/taint/sources.py,sha256=LSskC0JKwxbIsiyXU2Prz0sCyYQmGfsZQLqdBUQ11zU,2883
|
|
34
|
+
hackscan-0.1.0.dist-info/METADATA,sha256=J3YB65Kqr-VpQaDLQI-c-DU4F6TefIJr2XkKGCB0Rh4,7702
|
|
35
|
+
hackscan-0.1.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
36
|
+
hackscan-0.1.0.dist-info/entry_points.txt,sha256=MwyZQj1nZ-7l0tUv-x1CtLeryBbtnOleUZihDy6Fgxs,47
|
|
37
|
+
hackscan-0.1.0.dist-info/licenses/LICENSE,sha256=KkO2hUXEuGbXW1_AnaHLlx2GHIdQA8UmxOXLNay7yW8,1068
|
|
38
|
+
hackscan-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Khaled Awad
|
|
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.
|