run-codeql 1.1.1__tar.gz → 1.2.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.
- {run_codeql-1.1.1 → run_codeql-1.2.0}/PKG-INFO +17 -35
- {run_codeql-1.1.1 → run_codeql-1.2.0}/README.md +4 -0
- {run_codeql-1.1.1 → run_codeql-1.2.0}/pyproject.toml +21 -19
- {run_codeql-1.1.1 → run_codeql-1.2.0}/run_codeql/cli.py +26 -1
- {run_codeql-1.1.1 → run_codeql-1.2.0}/run_codeql/sarif.py +60 -4
- {run_codeql-1.1.1 → run_codeql-1.2.0}/run_codeql/settings.py +10 -0
- run_codeql-1.1.1/.github/workflows/ci.yml +0 -38
- run_codeql-1.1.1/.github/workflows/release.yml +0 -72
- run_codeql-1.1.1/.gitignore +0 -14
- run_codeql-1.1.1/Makefile +0 -40
- run_codeql-1.1.1/tests/fixtures/empty-code-quality.sarif +0 -14
- run_codeql-1.1.1/tests/fixtures/python-code-quality.sarif +0 -77
- run_codeql-1.1.1/tests/test_cleanup_reports.py +0 -39
- run_codeql-1.1.1/tests/test_cli.py +0 -104
- run_codeql-1.1.1/tests/test_cli_filters.py +0 -264
- run_codeql-1.1.1/tests/test_detect_langs.py +0 -79
- run_codeql-1.1.1/tests/test_download_integrity.py +0 -30
- run_codeql-1.1.1/tests/test_safe_extract.py +0 -35
- run_codeql-1.1.1/tests/test_sarif_filters.py +0 -255
- run_codeql-1.1.1/tests/test_summarize_sarif.py +0 -59
- {run_codeql-1.1.1 → run_codeql-1.2.0}/LICENSE +0 -0
- {run_codeql-1.1.1 → run_codeql-1.2.0}/run_codeql/__init__.py +0 -0
- {run_codeql-1.1.1 → run_codeql-1.2.0}/run_codeql/__main__.py +0 -0
- {run_codeql-1.1.1 → run_codeql-1.2.0}/run_codeql/download.py +0 -0
- {run_codeql-1.1.1 → run_codeql-1.2.0}/run_codeql/logging_utils.py +0 -0
- {run_codeql-1.1.1 → run_codeql-1.2.0}/run_codeql/scanner.py +0 -0
|
@@ -1,51 +1,28 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: run-codeql
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Run CodeQL code-quality analysis locally, mirroring the GitHub 'Code Quality' check
|
|
5
|
-
|
|
6
|
-
Project-URL: Repository, https://github.com/dereknorrbom/run-codeql
|
|
7
|
-
Project-URL: Bug Tracker, https://github.com/dereknorrbom/run-codeql/issues
|
|
8
|
-
Author-email: Derek Norrbom <dereknorrbom@gmail.com>
|
|
9
|
-
License: MIT License
|
|
10
|
-
|
|
11
|
-
Copyright (c) 2026 Derek Norrbom
|
|
12
|
-
|
|
13
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
-
in the Software without restriction, including without limitation the rights
|
|
16
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
-
furnished to do so, subject to the following conditions:
|
|
19
|
-
|
|
20
|
-
The above copyright notice and this permission notice shall be included in all
|
|
21
|
-
copies or substantial portions of the Software.
|
|
22
|
-
|
|
23
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
-
SOFTWARE.
|
|
5
|
+
License-Expression: MIT
|
|
30
6
|
License-File: LICENSE
|
|
31
|
-
Keywords: code-quality,
|
|
7
|
+
Keywords: codeql,static-analysis,code-quality,security,linting
|
|
8
|
+
Author: Derek Norrbom
|
|
9
|
+
Author-email: dereknorrbom@gmail.com
|
|
10
|
+
Requires-Python: >=3.10
|
|
32
11
|
Classifier: Development Status :: 4 - Beta
|
|
33
12
|
Classifier: Environment :: Console
|
|
34
13
|
Classifier: Intended Audience :: Developers
|
|
35
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
36
14
|
Classifier: Operating System :: OS Independent
|
|
37
15
|
Classifier: Programming Language :: Python :: 3
|
|
38
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
39
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
40
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
41
|
-
Classifier:
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
42
21
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
Requires-Dist: pytest-cov; extra == 'dev'
|
|
48
|
-
Requires-Dist: ruff; extra == 'dev'
|
|
22
|
+
Classifier: Topic :: Security
|
|
23
|
+
Project-URL: Bug Tracker, https://github.com/dereknorrbom/run-codeql/issues
|
|
24
|
+
Project-URL: Homepage, https://github.com/dereknorrbom/run-codeql
|
|
25
|
+
Project-URL: Repository, https://github.com/dereknorrbom/run-codeql
|
|
49
26
|
Description-Content-Type: text/markdown
|
|
50
27
|
|
|
51
28
|
# run-codeql
|
|
@@ -84,9 +61,11 @@ rcql --lang python,actions # scan multiple specific languages
|
|
|
84
61
|
| `--verbose`, `-v` | Print each finding with rule ID, location, and message |
|
|
85
62
|
| `--quiet`, `-q` | Suppress log output; print only final summaries (for agent/scripted use) |
|
|
86
63
|
| `--files` | Comma-separated file paths or fnmatch patterns to restrict findings to (e.g. `src/foo.py` or `src/*.py`) |
|
|
64
|
+
| `--exclude-files` | Comma-separated file paths or fnmatch patterns to exclude from findings (e.g. `src/generated/**`) |
|
|
87
65
|
| `--rule` | Comma-separated rule IDs or fnmatch patterns to restrict findings to (e.g. `py/unused-import` or `py/*`) |
|
|
88
66
|
| `--limit N` | Return at most N findings (after `--files`/`--rule` filtering) |
|
|
89
67
|
| `--offset N` | Skip the first N findings before applying `--limit` (for pagination) |
|
|
68
|
+
| `--include-third-party` | Include findings from third-party/vendor paths (default output suppresses common dependency noise) |
|
|
90
69
|
| `--keep-db` | Reuse existing databases instead of recreating them |
|
|
91
70
|
| `--keep-reports` | Do not delete prior SARIF reports before running |
|
|
92
71
|
| `--no-fail` | Exit 0 even if findings or scan errors exist |
|
|
@@ -164,6 +143,8 @@ Example output:
|
|
|
164
143
|
|
|
165
144
|
When a scan returns hundreds or thousands of findings, use `--files`, `--rule`, `--limit`, and `--offset` to slice the results. These flags work with both `--report-only` and live scans.
|
|
166
145
|
|
|
146
|
+
By default, summary output suppresses common third-party noise paths such as `node_modules`, `vendor`, and `.codeql` mirror artifacts. Use `--include-third-party` to opt in to those findings.
|
|
147
|
+
|
|
167
148
|
**Filter to a specific file:**
|
|
168
149
|
|
|
169
150
|
```sh
|
|
@@ -273,3 +254,4 @@ Contributions are welcome. Please:
|
|
|
273
254
|
## License
|
|
274
255
|
|
|
275
256
|
MIT
|
|
257
|
+
|
|
@@ -34,9 +34,11 @@ rcql --lang python,actions # scan multiple specific languages
|
|
|
34
34
|
| `--verbose`, `-v` | Print each finding with rule ID, location, and message |
|
|
35
35
|
| `--quiet`, `-q` | Suppress log output; print only final summaries (for agent/scripted use) |
|
|
36
36
|
| `--files` | Comma-separated file paths or fnmatch patterns to restrict findings to (e.g. `src/foo.py` or `src/*.py`) |
|
|
37
|
+
| `--exclude-files` | Comma-separated file paths or fnmatch patterns to exclude from findings (e.g. `src/generated/**`) |
|
|
37
38
|
| `--rule` | Comma-separated rule IDs or fnmatch patterns to restrict findings to (e.g. `py/unused-import` or `py/*`) |
|
|
38
39
|
| `--limit N` | Return at most N findings (after `--files`/`--rule` filtering) |
|
|
39
40
|
| `--offset N` | Skip the first N findings before applying `--limit` (for pagination) |
|
|
41
|
+
| `--include-third-party` | Include findings from third-party/vendor paths (default output suppresses common dependency noise) |
|
|
40
42
|
| `--keep-db` | Reuse existing databases instead of recreating them |
|
|
41
43
|
| `--keep-reports` | Do not delete prior SARIF reports before running |
|
|
42
44
|
| `--no-fail` | Exit 0 even if findings or scan errors exist |
|
|
@@ -114,6 +116,8 @@ Example output:
|
|
|
114
116
|
|
|
115
117
|
When a scan returns hundreds or thousands of findings, use `--files`, `--rule`, `--limit`, and `--offset` to slice the results. These flags work with both `--report-only` and live scans.
|
|
116
118
|
|
|
119
|
+
By default, summary output suppresses common third-party noise paths such as `node_modules`, `vendor`, and `.codeql` mirror artifacts. Use `--include-third-party` to opt in to those findings.
|
|
120
|
+
|
|
117
121
|
**Filter to a specific file:**
|
|
118
122
|
|
|
119
123
|
```sh
|
|
@@ -1,43 +1,49 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["
|
|
3
|
-
build-backend = "
|
|
2
|
+
requires = ["poetry-core"]
|
|
3
|
+
build-backend = "poetry.core.masonry.api"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "run-codeql"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.2.0"
|
|
8
8
|
description = "Run CodeQL code-quality analysis locally, mirroring the GitHub 'Code Quality' check"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
license =
|
|
10
|
+
license = "MIT"
|
|
11
11
|
authors = [{ name = "Derek Norrbom", email = "dereknorrbom@gmail.com" }]
|
|
12
|
-
requires-python = ">=3.10"
|
|
13
|
-
dependencies = []
|
|
14
12
|
keywords = ["codeql", "static-analysis", "code-quality", "security", "linting"]
|
|
15
13
|
classifiers = [
|
|
16
14
|
"Development Status :: 4 - Beta",
|
|
17
15
|
"Environment :: Console",
|
|
18
16
|
"Intended Audience :: Developers",
|
|
19
|
-
"License :: OSI Approved :: MIT License",
|
|
20
17
|
"Operating System :: OS Independent",
|
|
21
18
|
"Programming Language :: Python :: 3",
|
|
22
19
|
"Programming Language :: Python :: 3.10",
|
|
23
20
|
"Programming Language :: Python :: 3.11",
|
|
24
21
|
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
25
24
|
"Topic :: Software Development :: Quality Assurance",
|
|
26
25
|
"Topic :: Security",
|
|
27
26
|
]
|
|
27
|
+
requires-python = ">=3.10"
|
|
28
|
+
dependencies = []
|
|
28
29
|
|
|
29
30
|
[project.urls]
|
|
30
31
|
Homepage = "https://github.com/dereknorrbom/run-codeql"
|
|
31
32
|
Repository = "https://github.com/dereknorrbom/run-codeql"
|
|
32
33
|
"Bug Tracker" = "https://github.com/dereknorrbom/run-codeql/issues"
|
|
33
34
|
|
|
34
|
-
[project.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
[project.scripts]
|
|
36
|
+
run-codeql = "run_codeql.cli:main"
|
|
37
|
+
rcql = "run_codeql.cli:main"
|
|
38
|
+
|
|
39
|
+
[tool.poetry]
|
|
40
|
+
packages = [{ include = "run_codeql" }]
|
|
41
|
+
|
|
42
|
+
[tool.poetry.group.dev.dependencies]
|
|
43
|
+
pytest = ">=8.0"
|
|
44
|
+
pytest-cov = ">=6.0"
|
|
45
|
+
black = ">=25.0"
|
|
46
|
+
ruff = ">=0.9"
|
|
41
47
|
|
|
42
48
|
[tool.black]
|
|
43
49
|
line-length = 100
|
|
@@ -50,15 +56,11 @@ target-version = "py310"
|
|
|
50
56
|
[tool.ruff.lint]
|
|
51
57
|
select = ["E", "F", "W", "I"]
|
|
52
58
|
|
|
53
|
-
[project.scripts]
|
|
54
|
-
run-codeql = "run_codeql.cli:main"
|
|
55
|
-
rcql = "run_codeql.cli:main"
|
|
56
|
-
|
|
57
59
|
[tool.semantic_release]
|
|
58
60
|
version_toml = ["pyproject.toml:project.version"]
|
|
59
61
|
branch = "main"
|
|
60
62
|
changelog_file = "CHANGELOG.md"
|
|
61
|
-
build_command = "pip install
|
|
63
|
+
build_command = "pip install poetry && poetry build"
|
|
62
64
|
dist_path = "dist/"
|
|
63
65
|
upload_to_vcs_release = true
|
|
64
66
|
|
|
@@ -11,7 +11,7 @@ from run_codeql.download import fetch_codeql
|
|
|
11
11
|
from run_codeql.logging_utils import configure_logging, err, log
|
|
12
12
|
from run_codeql.sarif import build_sarif_summary
|
|
13
13
|
from run_codeql.scanner import cleanup_reports, detect_langs, run_lang
|
|
14
|
-
from run_codeql.settings import TOOLS_DIR
|
|
14
|
+
from run_codeql.settings import DEFAULT_SARIF_EXCLUDE_PATTERNS, TOOLS_DIR
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def main() -> None:
|
|
@@ -73,6 +73,22 @@ def main() -> None:
|
|
|
73
73
|
"(e.g. 'src/foo.py' or 'src/*.py')"
|
|
74
74
|
),
|
|
75
75
|
)
|
|
76
|
+
parser.add_argument(
|
|
77
|
+
"--exclude-files",
|
|
78
|
+
default=None,
|
|
79
|
+
help=(
|
|
80
|
+
"Comma-separated file paths (or fnmatch patterns) to exclude findings from. "
|
|
81
|
+
"Applied after URI normalization."
|
|
82
|
+
),
|
|
83
|
+
)
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
"--include-third-party",
|
|
86
|
+
action="store_true",
|
|
87
|
+
help=(
|
|
88
|
+
"Include third-party findings. By default, rcql suppresses common "
|
|
89
|
+
"noise paths like node_modules/vendor/.codeql."
|
|
90
|
+
),
|
|
91
|
+
)
|
|
76
92
|
parser.add_argument(
|
|
77
93
|
"--rule",
|
|
78
94
|
default=None,
|
|
@@ -102,6 +118,13 @@ def main() -> None:
|
|
|
102
118
|
print("[codeql-local] running in quiet mode", file=sys.stderr, flush=True)
|
|
103
119
|
|
|
104
120
|
file_patterns = [p.strip() for p in args.files.split(",") if p.strip()] if args.files else None
|
|
121
|
+
exclude_file_patterns: list[str] = (
|
|
122
|
+
[] if args.include_third_party else list(DEFAULT_SARIF_EXCLUDE_PATTERNS)
|
|
123
|
+
)
|
|
124
|
+
if args.exclude_files:
|
|
125
|
+
exclude_file_patterns.extend(
|
|
126
|
+
[p.strip() for p in args.exclude_files.split(",") if p.strip()]
|
|
127
|
+
)
|
|
105
128
|
rule_patterns = [p.strip() for p in args.rule.split(",") if p.strip()] if args.rule else None
|
|
106
129
|
|
|
107
130
|
repo_root = Path.cwd()
|
|
@@ -129,6 +152,7 @@ def main() -> None:
|
|
|
129
152
|
sarif,
|
|
130
153
|
verbose=args.verbose,
|
|
131
154
|
files=file_patterns,
|
|
155
|
+
exclude_files=exclude_file_patterns,
|
|
132
156
|
rules=rule_patterns,
|
|
133
157
|
limit=args.limit,
|
|
134
158
|
offset=args.offset,
|
|
@@ -184,6 +208,7 @@ def main() -> None:
|
|
|
184
208
|
sarif,
|
|
185
209
|
verbose=args.verbose,
|
|
186
210
|
files=file_patterns,
|
|
211
|
+
exclude_files=exclude_file_patterns,
|
|
187
212
|
rules=rule_patterns,
|
|
188
213
|
limit=args.limit,
|
|
189
214
|
offset=args.offset,
|
|
@@ -6,6 +6,8 @@ import re
|
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
|
|
9
|
+
_DB_MIRROR_RE = re.compile(r"(?:^|/)\.codeql/db-[^/]+/src/(?P<src>.+)$")
|
|
10
|
+
|
|
9
11
|
|
|
10
12
|
@dataclass(frozen=True)
|
|
11
13
|
class SarifSummary:
|
|
@@ -31,10 +33,47 @@ def _uri_matches(uri: str, patterns: list[str]) -> bool:
|
|
|
31
33
|
return False
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
def _normalize_uri(uri: str) -> str:
|
|
37
|
+
"""Normalize SARIF artifact URIs to stable, source-like paths.
|
|
38
|
+
|
|
39
|
+
CodeQL may emit artifact URIs that point into the generated database mirror,
|
|
40
|
+
e.g. ``.codeql/db-python/src/<abs-repo-path>/src/file.py``. This function
|
|
41
|
+
maps those back to repository-relative paths when possible so findings are
|
|
42
|
+
not shown twice (real path + mirror path).
|
|
43
|
+
"""
|
|
44
|
+
if not uri:
|
|
45
|
+
return ""
|
|
46
|
+
|
|
47
|
+
normalized = uri.replace("\\", "/")
|
|
48
|
+
if normalized.startswith("file://"):
|
|
49
|
+
normalized = normalized[7:]
|
|
50
|
+
|
|
51
|
+
match = _DB_MIRROR_RE.search(normalized)
|
|
52
|
+
if match:
|
|
53
|
+
normalized = match.group("src")
|
|
54
|
+
|
|
55
|
+
cwd_posix = str(Path.cwd().resolve()).replace("\\", "/")
|
|
56
|
+
cwd_no_leading = cwd_posix.lstrip("/")
|
|
57
|
+
if (
|
|
58
|
+
cwd_posix.startswith("/")
|
|
59
|
+
and not normalized.startswith("/")
|
|
60
|
+
and (normalized == cwd_no_leading or normalized.startswith(cwd_no_leading + "/"))
|
|
61
|
+
):
|
|
62
|
+
normalized = "/" + normalized
|
|
63
|
+
|
|
64
|
+
if normalized.startswith(cwd_posix + "/"):
|
|
65
|
+
normalized = normalized[len(cwd_posix) + 1 :]
|
|
66
|
+
elif normalized == cwd_posix:
|
|
67
|
+
normalized = "."
|
|
68
|
+
|
|
69
|
+
return normalized
|
|
70
|
+
|
|
71
|
+
|
|
34
72
|
def build_sarif_summary(
|
|
35
73
|
sarif: Path,
|
|
36
74
|
verbose: bool = False,
|
|
37
75
|
files: list[str] | None = None,
|
|
76
|
+
exclude_files: list[str] | None = None,
|
|
38
77
|
rules: list[str] | None = None,
|
|
39
78
|
limit: int | None = None,
|
|
40
79
|
offset: int = 0,
|
|
@@ -45,6 +84,7 @@ def build_sarif_summary(
|
|
|
45
84
|
sarif: Path to the ``.sarif`` file.
|
|
46
85
|
verbose: Include per-finding details in the output text.
|
|
47
86
|
files: Optional list of fnmatch patterns matched against artifact URIs.
|
|
87
|
+
exclude_files: Optional list of fnmatch patterns excluded from artifact URIs.
|
|
48
88
|
rules: Optional list of fnmatch patterns matched against rule IDs
|
|
49
89
|
(e.g. ``['py/unused-import']`` or ``['py/*']``).
|
|
50
90
|
limit: If set, return at most this many findings (after *offset*).
|
|
@@ -60,21 +100,37 @@ def build_sarif_summary(
|
|
|
60
100
|
# Collect all matching results first so we can apply offset/limit uniformly.
|
|
61
101
|
matched: list[dict] = []
|
|
62
102
|
rules_map: dict[str, dict] = {}
|
|
103
|
+
seen_keys: set[tuple[str, str, int | str, str, str]] = set()
|
|
63
104
|
|
|
64
105
|
for run in data.get("runs", []):
|
|
65
106
|
rules_map.update(
|
|
66
107
|
{r["id"]: r for r in run.get("tool", {}).get("driver", {}).get("rules", [])}
|
|
67
108
|
)
|
|
68
109
|
for result in run.get("results", []):
|
|
110
|
+
loc = result.get("locations", [{}])[0]
|
|
111
|
+
phys = loc.get("physicalLocation", {})
|
|
112
|
+
raw_uri = phys.get("artifactLocation", {}).get("uri", "")
|
|
113
|
+
uri = _normalize_uri(raw_uri)
|
|
114
|
+
line = phys.get("region", {}).get("startLine", "")
|
|
115
|
+
rule_id = result.get("ruleId", "")
|
|
116
|
+
level = result.get("level", "warning")
|
|
117
|
+
message = re.sub(
|
|
118
|
+
r"\[([^\]]+)\]\(\d+\)", r"\1", result.get("message", {}).get("text", "")
|
|
119
|
+
)
|
|
120
|
+
|
|
69
121
|
if files is not None:
|
|
70
|
-
loc = result.get("locations", [{}])[0]
|
|
71
|
-
uri = loc.get("physicalLocation", {}).get("artifactLocation", {}).get("uri", "")
|
|
72
122
|
if not _uri_matches(uri, files):
|
|
73
123
|
continue
|
|
124
|
+
if exclude_files is not None and _uri_matches(uri, exclude_files):
|
|
125
|
+
continue
|
|
74
126
|
if rules is not None:
|
|
75
|
-
rule_id = result.get("ruleId", "")
|
|
76
127
|
if not any(fnmatch.fnmatch(rule_id, pat) for pat in rules):
|
|
77
128
|
continue
|
|
129
|
+
|
|
130
|
+
dedupe_key = (rule_id, level, line, uri, message)
|
|
131
|
+
if dedupe_key in seen_keys:
|
|
132
|
+
continue
|
|
133
|
+
seen_keys.add(dedupe_key)
|
|
78
134
|
matched.append(result)
|
|
79
135
|
|
|
80
136
|
# Apply pagination.
|
|
@@ -97,7 +153,7 @@ def build_sarif_summary(
|
|
|
97
153
|
message = re.sub(r"\[([^\]]+)\]\(\d+\)", r"\1", message)
|
|
98
154
|
loc = result.get("locations", [{}])[0]
|
|
99
155
|
phys = loc.get("physicalLocation", {})
|
|
100
|
-
uri = phys.get("artifactLocation", {}).get("uri", "")
|
|
156
|
+
uri = _normalize_uri(phys.get("artifactLocation", {}).get("uri", ""))
|
|
101
157
|
line = phys.get("region", {}).get("startLine", "")
|
|
102
158
|
location = f"{uri}:{line}" if line else uri
|
|
103
159
|
finding_lines.append(
|
|
@@ -76,3 +76,13 @@ LANG_CONFIG = {
|
|
|
76
76
|
"suite": "codeql/actions-queries:codeql-suites/actions-security-and-quality.qls",
|
|
77
77
|
},
|
|
78
78
|
}
|
|
79
|
+
|
|
80
|
+
# Default SARIF artifact URI excludes for summary output. These reduce triage
|
|
81
|
+
# noise from third-party and generated paths while preserving an opt-in path
|
|
82
|
+
# to include them via CLI flags.
|
|
83
|
+
DEFAULT_SARIF_EXCLUDE_PATTERNS: list[str] = [
|
|
84
|
+
"**/node_modules/**",
|
|
85
|
+
"**/vendor/**",
|
|
86
|
+
".codeql/**",
|
|
87
|
+
"**/.codeql/**",
|
|
88
|
+
]
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: ["**"]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: ["**"]
|
|
8
|
-
|
|
9
|
-
permissions:
|
|
10
|
-
contents: read
|
|
11
|
-
|
|
12
|
-
jobs:
|
|
13
|
-
lint:
|
|
14
|
-
name: Lint
|
|
15
|
-
runs-on: ubuntu-latest
|
|
16
|
-
steps:
|
|
17
|
-
- uses: actions/checkout@v4
|
|
18
|
-
- uses: actions/setup-python@v5
|
|
19
|
-
with:
|
|
20
|
-
python-version: "3.12"
|
|
21
|
-
- run: pip install black ruff
|
|
22
|
-
- run: black --check run_codeql tests
|
|
23
|
-
- run: ruff check run_codeql tests
|
|
24
|
-
|
|
25
|
-
test:
|
|
26
|
-
name: Test (Python ${{ matrix.python-version }})
|
|
27
|
-
runs-on: ubuntu-latest
|
|
28
|
-
strategy:
|
|
29
|
-
fail-fast: false
|
|
30
|
-
matrix:
|
|
31
|
-
python-version: ["3.10", "3.11", "3.12"]
|
|
32
|
-
steps:
|
|
33
|
-
- uses: actions/checkout@v4
|
|
34
|
-
- uses: actions/setup-python@v5
|
|
35
|
-
with:
|
|
36
|
-
python-version: ${{ matrix.python-version }}
|
|
37
|
-
- run: pip install -e ".[dev]"
|
|
38
|
-
- run: pytest tests/ -v
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
name: Release
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
|
|
7
|
-
permissions:
|
|
8
|
-
contents: write
|
|
9
|
-
id-token: write # required for PyPI trusted publishing
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
ci:
|
|
13
|
-
name: Test (Python ${{ matrix.python-version }})
|
|
14
|
-
runs-on: ubuntu-latest
|
|
15
|
-
permissions:
|
|
16
|
-
contents: read
|
|
17
|
-
strategy:
|
|
18
|
-
fail-fast: false
|
|
19
|
-
matrix:
|
|
20
|
-
python-version: ["3.10", "3.11", "3.12"]
|
|
21
|
-
steps:
|
|
22
|
-
- uses: actions/checkout@v4
|
|
23
|
-
- uses: actions/setup-python@v5
|
|
24
|
-
with:
|
|
25
|
-
python-version: ${{ matrix.python-version }}
|
|
26
|
-
- run: pip install -e ".[dev]"
|
|
27
|
-
- run: pytest tests/ -v
|
|
28
|
-
|
|
29
|
-
lint:
|
|
30
|
-
name: Lint
|
|
31
|
-
runs-on: ubuntu-latest
|
|
32
|
-
permissions:
|
|
33
|
-
contents: read
|
|
34
|
-
steps:
|
|
35
|
-
- uses: actions/checkout@v4
|
|
36
|
-
- uses: actions/setup-python@v5
|
|
37
|
-
with:
|
|
38
|
-
python-version: "3.12"
|
|
39
|
-
- run: pip install black ruff
|
|
40
|
-
- run: black --check run_codeql tests
|
|
41
|
-
- run: ruff check run_codeql tests
|
|
42
|
-
|
|
43
|
-
release:
|
|
44
|
-
name: Semantic Release
|
|
45
|
-
runs-on: ubuntu-latest
|
|
46
|
-
needs: [ci, lint]
|
|
47
|
-
concurrency: release
|
|
48
|
-
steps:
|
|
49
|
-
- uses: actions/checkout@v4
|
|
50
|
-
with:
|
|
51
|
-
fetch-depth: 0
|
|
52
|
-
token: ${{ secrets.GITHUB_TOKEN }}
|
|
53
|
-
|
|
54
|
-
- uses: actions/setup-python@v5
|
|
55
|
-
with:
|
|
56
|
-
python-version: "3.12"
|
|
57
|
-
|
|
58
|
-
- run: pip install python-semantic-release build twine
|
|
59
|
-
|
|
60
|
-
- name: Semantic Release
|
|
61
|
-
id: release
|
|
62
|
-
env:
|
|
63
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
64
|
-
run: semantic-release version --push
|
|
65
|
-
|
|
66
|
-
- name: Build distribution
|
|
67
|
-
if: steps.release.outputs.released == 'true'
|
|
68
|
-
run: python -m build
|
|
69
|
-
|
|
70
|
-
- name: Publish to PyPI
|
|
71
|
-
if: steps.release.outputs.released == 'true'
|
|
72
|
-
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
run_codeql-1.1.1/.gitignore
DELETED
run_codeql-1.1.1/Makefile
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
.PHONY: help test lint fmt fmt-check typecheck check fix install
|
|
2
|
-
|
|
3
|
-
PYTHON := python
|
|
4
|
-
SRC := run_codeql tests
|
|
5
|
-
|
|
6
|
-
help:
|
|
7
|
-
@echo "Usage: make <target>"
|
|
8
|
-
@echo ""
|
|
9
|
-
@echo " test Run the test suite"
|
|
10
|
-
@echo " cov Run tests with coverage report"
|
|
11
|
-
@echo " lint Run ruff (check only)"
|
|
12
|
-
@echo " fmt Auto-format with black and ruff --fix"
|
|
13
|
-
@echo " fmt-check Check formatting without modifying files"
|
|
14
|
-
@echo " fix lint + fmt combined (auto-fix everything)"
|
|
15
|
-
@echo " check fmt-check + lint (CI-safe, no modifications)"
|
|
16
|
-
@echo " install Install package in editable mode with dev deps"
|
|
17
|
-
|
|
18
|
-
test:
|
|
19
|
-
$(PYTHON) -m pytest tests/
|
|
20
|
-
|
|
21
|
-
cov:
|
|
22
|
-
$(PYTHON) -m pytest tests/ --cov=run_codeql --cov-report=term-missing
|
|
23
|
-
|
|
24
|
-
lint:
|
|
25
|
-
ruff check $(SRC)
|
|
26
|
-
|
|
27
|
-
fmt:
|
|
28
|
-
black $(SRC)
|
|
29
|
-
ruff check --fix $(SRC)
|
|
30
|
-
|
|
31
|
-
fmt-check:
|
|
32
|
-
black --check $(SRC)
|
|
33
|
-
ruff check $(SRC)
|
|
34
|
-
|
|
35
|
-
fix: fmt lint
|
|
36
|
-
|
|
37
|
-
check: fmt-check lint
|
|
38
|
-
|
|
39
|
-
install:
|
|
40
|
-
pip install -e ".[dev]"
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "2.1.0",
|
|
3
|
-
"runs": [
|
|
4
|
-
{
|
|
5
|
-
"tool": {
|
|
6
|
-
"driver": {
|
|
7
|
-
"name": "CodeQL",
|
|
8
|
-
"rules": [
|
|
9
|
-
{
|
|
10
|
-
"id": "py/sql-injection",
|
|
11
|
-
"name": "SqlInjection",
|
|
12
|
-
"shortDescription": { "text": "SQL injection" },
|
|
13
|
-
"defaultConfiguration": { "level": "error" }
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"id": "py/unused-import",
|
|
17
|
-
"name": "UnusedImport",
|
|
18
|
-
"shortDescription": { "text": "Unused import" },
|
|
19
|
-
"defaultConfiguration": { "level": "warning" }
|
|
20
|
-
}
|
|
21
|
-
]
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"results": [
|
|
25
|
-
{
|
|
26
|
-
"ruleId": "py/sql-injection",
|
|
27
|
-
"level": "error",
|
|
28
|
-
"message": { "text": "This query depends on [user-provided value](1)." },
|
|
29
|
-
"locations": [
|
|
30
|
-
{
|
|
31
|
-
"physicalLocation": {
|
|
32
|
-
"artifactLocation": { "uri": "src/db.py", "uriBaseId": "%SRCROOT%" },
|
|
33
|
-
"region": { "startLine": 42, "startColumn": 5 }
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
"relatedLocations": [
|
|
38
|
-
{
|
|
39
|
-
"id": 1,
|
|
40
|
-
"physicalLocation": {
|
|
41
|
-
"artifactLocation": { "uri": "src/views.py", "uriBaseId": "%SRCROOT%" },
|
|
42
|
-
"region": { "startLine": 10 }
|
|
43
|
-
},
|
|
44
|
-
"message": { "text": "user-provided value" }
|
|
45
|
-
}
|
|
46
|
-
]
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"ruleId": "py/unused-import",
|
|
50
|
-
"level": "warning",
|
|
51
|
-
"message": { "text": "Import of 'os' is not used." },
|
|
52
|
-
"locations": [
|
|
53
|
-
{
|
|
54
|
-
"physicalLocation": {
|
|
55
|
-
"artifactLocation": { "uri": "src/utils.py", "uriBaseId": "%SRCROOT%" },
|
|
56
|
-
"region": { "startLine": 3, "startColumn": 1 }
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
"ruleId": "py/unused-import",
|
|
63
|
-
"level": "warning",
|
|
64
|
-
"message": { "text": "Import of 'sys' is not used." },
|
|
65
|
-
"locations": [
|
|
66
|
-
{
|
|
67
|
-
"physicalLocation": {
|
|
68
|
-
"artifactLocation": { "uri": "src/utils.py", "uriBaseId": "%SRCROOT%" },
|
|
69
|
-
"region": { "startLine": 4, "startColumn": 1 }
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
]
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
}
|