codejury 0.17.1__tar.gz → 0.18.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.
- codejury-0.18.0/PKG-INFO +147 -0
- codejury-0.18.0/README.md +116 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/__init__.py +3 -2
- {codejury-0.17.1 → codejury-0.18.0}/codejury/cli.py +1 -1
- codejury-0.18.0/codejury/data/frameworks/python/celery.md +36 -0
- {codejury-0.17.1/codejury/data/frameworks → codejury-0.18.0/codejury/data/frameworks/python}/django.md +9 -7
- {codejury-0.17.1 → codejury-0.18.0}/codejury/data/languages/python.md +4 -4
- {codejury-0.17.1/codejury/data/methodology → codejury-0.18.0/codejury/data/methodologies}/repo-review.md +66 -36
- {codejury-0.17.1/codejury/data/methodology → codejury-0.18.0/codejury/data/methodologies}/security-review-memory.md +4 -4
- codejury-0.18.0/codejury/data/protocols/oauth.md +55 -0
- codejury-0.18.0/codejury/data/vulnerabilities/SKILL.md +59 -0
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/code-injection.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/cross-site-request-forgery.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/cross-site-scripting.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/http-response-splitting.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/improper-authentication.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/information-exposure.md +5 -5
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/insecure-cryptography.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/insecure-deserialization.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/insecure-direct-object-reference.md +2 -2
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/insecure-transport.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/mass-assignment.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/open-redirect.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/path-traversal.md +3 -3
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/race-condition.md +3 -3
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/replay-attack.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/server-side-request-forgery.md +2 -2
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/server-side-template-injection.md +3 -3
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/session-fixation.md +2 -2
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/sql-injection.md +1 -1
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/xml-external-entity.md +2 -2
- {codejury-0.17.1 → codejury-0.18.0}/codejury/diff/debate.py +6 -6
- {codejury-0.17.1 → codejury-0.18.0}/codejury/diff/debate_prompts.py +7 -7
- {codejury-0.17.1 → codejury-0.18.0}/codejury/diff/engine.py +5 -5
- {codejury-0.17.1 → codejury-0.18.0}/codejury/diff/prompts.py +5 -5
- {codejury-0.17.1 → codejury-0.18.0}/codejury/diff/runner.py +1 -1
- codejury-0.18.0/codejury/diff/vulnerabilities.py +75 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/domain/__init__.py +1 -1
- {codejury-0.17.1 → codejury-0.18.0}/codejury/guides.py +35 -11
- {codejury-0.17.1 → codejury-0.18.0}/codejury/mddoc.py +10 -8
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/__init__.py +1 -1
- codejury-0.18.0/codejury/repo/model.py +106 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/repo/scaffold.py +48 -10
- {codejury-0.17.1 → codejury-0.18.0}/codejury/resources.py +3 -2
- codejury-0.18.0/codejury.egg-info/PKG-INFO +147 -0
- codejury-0.18.0/codejury.egg-info/SOURCES.txt +85 -0
- {codejury-0.17.1 → codejury-0.18.0}/pyproject.toml +1 -1
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_diff_engine.py +2 -2
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_guides.py +19 -3
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_repo_model.py +14 -3
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_repo_scaffold.py +1 -1
- codejury-0.17.1/tests/test_rules.py → codejury-0.18.0/tests/test_vulnerabilities.py +31 -31
- codejury-0.17.1/PKG-INFO +0 -135
- codejury-0.17.1/README.md +0 -104
- codejury-0.17.1/codejury/data/rules/SKILL.md +0 -58
- codejury-0.17.1/codejury/diff/rules.py +0 -74
- codejury-0.17.1/codejury/repo/model.py +0 -61
- codejury-0.17.1/codejury.egg-info/PKG-INFO +0 -135
- codejury-0.17.1/codejury.egg-info/SOURCES.txt +0 -83
- {codejury-0.17.1 → codejury-0.18.0}/LICENSE +0 -0
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/business-logic.md +0 -0
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/command-injection.md +0 -0
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/hardcoded-secrets.md +0 -0
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/jwt-validation.md +0 -0
- {codejury-0.17.1/codejury/data/rules → codejury-0.18.0/codejury/data/vulnerabilities}/missing-authorization.md +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/diff/__init__.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/diff/findings_filter.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/domain/finding.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/json_parse.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/anthropic.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/base.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/factory.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/litellm.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/mock.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/openai.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/openai_format.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/providers/retry.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/repo/__init__.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury/report.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury.egg-info/dependency_links.txt +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury.egg-info/entry_points.txt +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury.egg-info/requires.txt +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/codejury.egg-info/top_level.txt +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/setup.cfg +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_anthropic_provider.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_cli_audit.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_diff_debate.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_json_parse.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_litellm_provider.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_mddoc.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_openai_format.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_openai_provider.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_report.py +0 -0
- {codejury-0.17.1 → codejury-0.18.0}/tests/test_retry_provider.py +0 -0
codejury-0.18.0/PKG-INFO
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codejury
|
|
3
|
+
Version: 0.18.0
|
|
4
|
+
Summary: AI code security review: an adversarial diff-audit engine and an agent-driven whole-repo review methodology, with security knowledge as rich rules
|
|
5
|
+
Author: AISecLabs
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/aiseclabs/codejury
|
|
8
|
+
Project-URL: Repository, https://github.com/aiseclabs/codejury
|
|
9
|
+
Keywords: security,appsec,static analysis,llm,owasp,asvs,code review
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Topic :: Security
|
|
13
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: pyyaml>=6.0
|
|
20
|
+
Requires-Dist: json-repair>=0.30
|
|
21
|
+
Provides-Extra: anthropic
|
|
22
|
+
Requires-Dist: anthropic>=0.40; extra == "anthropic"
|
|
23
|
+
Provides-Extra: openai
|
|
24
|
+
Requires-Dist: openai>=1.0; extra == "openai"
|
|
25
|
+
Provides-Extra: litellm
|
|
26
|
+
Requires-Dist: litellm>=1.0; extra == "litellm"
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
29
|
+
Requires-Dist: jsonschema>=4.0; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
██████╗ ██████╗ ██████╗ ███████╗ ██╗██╗ ██╗██████╗ ██╗ ██╗
|
|
34
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██║██║ ██║██╔══██╗╚██╗ ██╔╝
|
|
35
|
+
██║ ██║ ██║██║ ██║█████╗ ██║██║ ██║██████╔╝ ╚████╔╝
|
|
36
|
+
██║ ██║ ██║██║ ██║██╔══╝ ██ ██║██║ ██║██╔══██╗ ╚██╔╝
|
|
37
|
+
╚██████╗╚██████╔╝██████╔╝███████╗╚█████╔╝╚██████╔╝██║ ██║ ██║
|
|
38
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
> AI code security review for diffs and whole repositories.
|
|
42
|
+
|
|
43
|
+
It runs two paths matched to their nature.
|
|
44
|
+
|
|
45
|
+
- **Diff Review** is coded. It audits a pull request diff for newly introduced
|
|
46
|
+
exploitable risk, as a single balanced LLM call or an adversarial Finder,
|
|
47
|
+
Challenger, and Judge pass that trades roughly 3x the cost for extra recall on
|
|
48
|
+
subtle flaws that span files.
|
|
49
|
+
- **Repo Review** is agent driven. It is a methodology an interactive agent such
|
|
50
|
+
as Claude Code or Codex runs to map a codebase attack surface, trace inputs to
|
|
51
|
+
sinks across files, verify issues with a real PoC, and iterate over rounds with
|
|
52
|
+
a persistent memory. A whole repository is too large for one LLM call, so it
|
|
53
|
+
ships the methodology and scaffolds the workspace instead of running a
|
|
54
|
+
pipeline.
|
|
55
|
+
|
|
56
|
+
Security knowledge lives in rich vulnerability classes under `codejury/data/vulnerabilities/*.md`, with a
|
|
57
|
+
vulnerable and a secure example per language, injected into the audit prompt
|
|
58
|
+
rather than buried in code.
|
|
59
|
+
|
|
60
|
+
## Install
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install codejury # core
|
|
64
|
+
pip install "codejury[anthropic]" # add a backend, also openai or litellm
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Diff Review
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# audit a diff file
|
|
71
|
+
codejury review diff --diff-file changes.diff
|
|
72
|
+
|
|
73
|
+
# audit a git range in a repo
|
|
74
|
+
codejury review diff --repo /path/to/app --git-range origin/main...HEAD
|
|
75
|
+
|
|
76
|
+
# from stdin
|
|
77
|
+
git diff HEAD~1 | codejury review diff
|
|
78
|
+
|
|
79
|
+
# adversarial mode, more recall on subtle flaws, about 3x the cost
|
|
80
|
+
codejury review diff --diff-file changes.diff --mode adversarial
|
|
81
|
+
|
|
82
|
+
# CI gate and SARIF
|
|
83
|
+
codejury review diff --diff-file changes.diff --format sarif --fail-on high
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
|
|
87
|
+
the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
|
|
88
|
+
variables. `codejury review diff --dry-run` exercises the engine with a mock
|
|
89
|
+
provider and no key, and falls back to a built in demo diff when you pass none.
|
|
90
|
+
|
|
91
|
+
### Choosing a Model and Mode
|
|
92
|
+
|
|
93
|
+
Detection quality is dominated by the model first, then the mode. On real diff
|
|
94
|
+
probes:
|
|
95
|
+
|
|
96
|
+
- A strong model at the Claude Sonnet tier in standard mode caught every planted
|
|
97
|
+
vulnerability with almost no false positives. A weaker model raised false
|
|
98
|
+
positives in both modes, so the model is the lever that matters most.
|
|
99
|
+
- Adversarial mode did not lower false positives over standard on those probes
|
|
100
|
+
and costs about 3x. Reach for it to gain recall on subtle logic that spans
|
|
101
|
+
files, not as a way to cut false positives.
|
|
102
|
+
|
|
103
|
+
Default to standard mode with a strong model, set with `--model` or
|
|
104
|
+
`CODEJURY_MODEL`. False positives are held down by the do not report list and the
|
|
105
|
+
post filter, not by the mode.
|
|
106
|
+
|
|
107
|
+
### Use in CI with GitHub Actions
|
|
108
|
+
|
|
109
|
+
Audit every pull request and surface findings in the code scanning tab. Copy
|
|
110
|
+
`examples/codejury-pr-review.yml` into `.github/workflows/`, add a
|
|
111
|
+
`CODEJURY_API_KEY` repository secret, and it will
|
|
112
|
+
|
|
113
|
+
1. diff the pull request against its base with `--git-range origin/<base>...HEAD`,
|
|
114
|
+
2. write SARIF and upload it with `github/codeql-action/upload-sarif`,
|
|
115
|
+
3. fail the check on a HIGH or CRITICAL finding with `--fail-on high`.
|
|
116
|
+
|
|
117
|
+
The job makes one model call per pull request in standard mode. The SARIF is
|
|
118
|
+
uploaded even when the gate fails, so findings always show up on the pull
|
|
119
|
+
request.
|
|
120
|
+
|
|
121
|
+
## Repo Review
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
codejury review repo /path/to/your/repo
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This scaffolds a review workspace with `entrypoints/`, `issues/`, `analysis/`,
|
|
128
|
+
and a `security-review-memory.md`, seeds the entrypoint inventory from a
|
|
129
|
+
deterministic scan, and prints the methodology. Run it with an interactive agent.
|
|
130
|
+
It reads the methodology and the vulnerability classes, maps the attack surface, traces inputs to
|
|
131
|
+
sinks across files, records high confidence issues with a PoC, and asks you to
|
|
132
|
+
confirm credentials or false positives along the way. Nothing runs against
|
|
133
|
+
production.
|
|
134
|
+
|
|
135
|
+
## Findings
|
|
136
|
+
|
|
137
|
+
Each finding carries a file and line, a severity and category, a concrete exploit
|
|
138
|
+
scenario, a recommendation, and a confidence. A false positive filter drops test
|
|
139
|
+
paths, mock paths, and low confidence noise. The model is also told not to report
|
|
140
|
+
dependency CVEs, style notes, speculation, or risks that only matter when
|
|
141
|
+
production config leaks.
|
|
142
|
+
|
|
143
|
+
## Extending
|
|
144
|
+
|
|
145
|
+
Add a vulnerability class by dropping a new file `codejury/data/vulnerabilities/<class>.md`
|
|
146
|
+
with the standard frontmatter of title, impact, tags, and triggers plus a
|
|
147
|
+
vulnerable and a secure example. It is data, no code change needed.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
```
|
|
2
|
+
██████╗ ██████╗ ██████╗ ███████╗ ██╗██╗ ██╗██████╗ ██╗ ██╗
|
|
3
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██║██║ ██║██╔══██╗╚██╗ ██╔╝
|
|
4
|
+
██║ ██║ ██║██║ ██║█████╗ ██║██║ ██║██████╔╝ ╚████╔╝
|
|
5
|
+
██║ ██║ ██║██║ ██║██╔══╝ ██ ██║██║ ██║██╔══██╗ ╚██╔╝
|
|
6
|
+
╚██████╗╚██████╔╝██████╔╝███████╗╚█████╔╝╚██████╔╝██║ ██║ ██║
|
|
7
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
> AI code security review for diffs and whole repositories.
|
|
11
|
+
|
|
12
|
+
It runs two paths matched to their nature.
|
|
13
|
+
|
|
14
|
+
- **Diff Review** is coded. It audits a pull request diff for newly introduced
|
|
15
|
+
exploitable risk, as a single balanced LLM call or an adversarial Finder,
|
|
16
|
+
Challenger, and Judge pass that trades roughly 3x the cost for extra recall on
|
|
17
|
+
subtle flaws that span files.
|
|
18
|
+
- **Repo Review** is agent driven. It is a methodology an interactive agent such
|
|
19
|
+
as Claude Code or Codex runs to map a codebase attack surface, trace inputs to
|
|
20
|
+
sinks across files, verify issues with a real PoC, and iterate over rounds with
|
|
21
|
+
a persistent memory. A whole repository is too large for one LLM call, so it
|
|
22
|
+
ships the methodology and scaffolds the workspace instead of running a
|
|
23
|
+
pipeline.
|
|
24
|
+
|
|
25
|
+
Security knowledge lives in rich vulnerability classes under `codejury/data/vulnerabilities/*.md`, with a
|
|
26
|
+
vulnerable and a secure example per language, injected into the audit prompt
|
|
27
|
+
rather than buried in code.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install codejury # core
|
|
33
|
+
pip install "codejury[anthropic]" # add a backend, also openai or litellm
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Diff Review
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# audit a diff file
|
|
40
|
+
codejury review diff --diff-file changes.diff
|
|
41
|
+
|
|
42
|
+
# audit a git range in a repo
|
|
43
|
+
codejury review diff --repo /path/to/app --git-range origin/main...HEAD
|
|
44
|
+
|
|
45
|
+
# from stdin
|
|
46
|
+
git diff HEAD~1 | codejury review diff
|
|
47
|
+
|
|
48
|
+
# adversarial mode, more recall on subtle flaws, about 3x the cost
|
|
49
|
+
codejury review diff --diff-file changes.diff --mode adversarial
|
|
50
|
+
|
|
51
|
+
# CI gate and SARIF
|
|
52
|
+
codejury review diff --diff-file changes.diff --format sarif --fail-on high
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
|
|
56
|
+
the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
|
|
57
|
+
variables. `codejury review diff --dry-run` exercises the engine with a mock
|
|
58
|
+
provider and no key, and falls back to a built in demo diff when you pass none.
|
|
59
|
+
|
|
60
|
+
### Choosing a Model and Mode
|
|
61
|
+
|
|
62
|
+
Detection quality is dominated by the model first, then the mode. On real diff
|
|
63
|
+
probes:
|
|
64
|
+
|
|
65
|
+
- A strong model at the Claude Sonnet tier in standard mode caught every planted
|
|
66
|
+
vulnerability with almost no false positives. A weaker model raised false
|
|
67
|
+
positives in both modes, so the model is the lever that matters most.
|
|
68
|
+
- Adversarial mode did not lower false positives over standard on those probes
|
|
69
|
+
and costs about 3x. Reach for it to gain recall on subtle logic that spans
|
|
70
|
+
files, not as a way to cut false positives.
|
|
71
|
+
|
|
72
|
+
Default to standard mode with a strong model, set with `--model` or
|
|
73
|
+
`CODEJURY_MODEL`. False positives are held down by the do not report list and the
|
|
74
|
+
post filter, not by the mode.
|
|
75
|
+
|
|
76
|
+
### Use in CI with GitHub Actions
|
|
77
|
+
|
|
78
|
+
Audit every pull request and surface findings in the code scanning tab. Copy
|
|
79
|
+
`examples/codejury-pr-review.yml` into `.github/workflows/`, add a
|
|
80
|
+
`CODEJURY_API_KEY` repository secret, and it will
|
|
81
|
+
|
|
82
|
+
1. diff the pull request against its base with `--git-range origin/<base>...HEAD`,
|
|
83
|
+
2. write SARIF and upload it with `github/codeql-action/upload-sarif`,
|
|
84
|
+
3. fail the check on a HIGH or CRITICAL finding with `--fail-on high`.
|
|
85
|
+
|
|
86
|
+
The job makes one model call per pull request in standard mode. The SARIF is
|
|
87
|
+
uploaded even when the gate fails, so findings always show up on the pull
|
|
88
|
+
request.
|
|
89
|
+
|
|
90
|
+
## Repo Review
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
codejury review repo /path/to/your/repo
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
This scaffolds a review workspace with `entrypoints/`, `issues/`, `analysis/`,
|
|
97
|
+
and a `security-review-memory.md`, seeds the entrypoint inventory from a
|
|
98
|
+
deterministic scan, and prints the methodology. Run it with an interactive agent.
|
|
99
|
+
It reads the methodology and the vulnerability classes, maps the attack surface, traces inputs to
|
|
100
|
+
sinks across files, records high confidence issues with a PoC, and asks you to
|
|
101
|
+
confirm credentials or false positives along the way. Nothing runs against
|
|
102
|
+
production.
|
|
103
|
+
|
|
104
|
+
## Findings
|
|
105
|
+
|
|
106
|
+
Each finding carries a file and line, a severity and category, a concrete exploit
|
|
107
|
+
scenario, a recommendation, and a confidence. A false positive filter drops test
|
|
108
|
+
paths, mock paths, and low confidence noise. The model is also told not to report
|
|
109
|
+
dependency CVEs, style notes, speculation, or risks that only matter when
|
|
110
|
+
production config leaks.
|
|
111
|
+
|
|
112
|
+
## Extending
|
|
113
|
+
|
|
114
|
+
Add a vulnerability class by dropping a new file `codejury/data/vulnerabilities/<class>.md`
|
|
115
|
+
with the standard frontmatter of title, impact, tags, and triggers plus a
|
|
116
|
+
vulnerable and a secure example. It is data, no code change needed.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""AI code security review tool.
|
|
2
2
|
|
|
3
3
|
Two paths matched to their nature: a coded diff-audit engine (standard single
|
|
4
4
|
call or adversarial Finder/Challenger/Judge), and a whole-repo review run as a
|
|
5
5
|
methodology by an interactive agent. Security knowledge lives in rich markdown
|
|
6
|
-
|
|
6
|
+
vulnerability classes (data/vulnerabilities) injected into the audit prompt, not
|
|
7
|
+
in a rendered schema.
|
|
7
8
|
"""
|
|
8
9
|
|
|
9
10
|
from importlib.metadata import PackageNotFoundError, version
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: celery
|
|
3
|
+
title: Celery
|
|
4
|
+
kind: framework
|
|
5
|
+
language: python
|
|
6
|
+
detect:
|
|
7
|
+
imports: ["celery", "shared_task"]
|
|
8
|
+
entrypoint_files: ["*tasks.py", "*/tasks/*.py"]
|
|
9
|
+
entrypoint_markers: ["@shared_task", "@app.task", "@celery_app.task", "@periodic_task", ".delay(", ".apply_async(", "crontab("]
|
|
10
|
+
---
|
|
11
|
+
# Celery Review Notes
|
|
12
|
+
|
|
13
|
+
A task is an entrypoint, not just glue. Its arguments are attacker-influenced
|
|
14
|
+
whenever the enqueue site passes request input through, so review a task the same
|
|
15
|
+
way as an HTTP handler. The web view that calls `.delay()` or `.apply_async()` is
|
|
16
|
+
the producer, and the task body is where the value lands.
|
|
17
|
+
|
|
18
|
+
## Entrypoints
|
|
19
|
+
- Task definitions in `tasks.py` or a `tasks/` package, marked by `@shared_task`,
|
|
20
|
+
`@app.task`, or `@celery_app.task`. Periodic tasks wired by `crontab()` or a
|
|
21
|
+
beat schedule run with no caller, so their inputs are config or stored state.
|
|
22
|
+
- Trace each task back to its `.delay(...)` and `.apply_async(...)` callers to see
|
|
23
|
+
which arguments are user-controlled.
|
|
24
|
+
|
|
25
|
+
## What to Hunt
|
|
26
|
+
- A task that fetches a URL, runs a command, opens a file path, or renders a
|
|
27
|
+
template from an argument, the same sink classes as a web handler, now reached
|
|
28
|
+
off the request cycle.
|
|
29
|
+
- Authorization re-check. A producer that checked the caller does not carry that
|
|
30
|
+
identity into the task, so a task that acts on a resource by an id in its
|
|
31
|
+
arguments needs its own owner or tenant check.
|
|
32
|
+
- Secret and token exposure. A task that logs full request headers, a response
|
|
33
|
+
body, or a fetched credential leaks it into worker logs. See the
|
|
34
|
+
information-exposure vulnerability class.
|
|
35
|
+
- Replayable or duplicate enqueue. A task with a side effect that is enqueued from
|
|
36
|
+
an unauthenticated or replayable producer runs more than once.
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
id: django
|
|
3
3
|
title: Django
|
|
4
4
|
kind: framework
|
|
5
|
+
language: python
|
|
5
6
|
detect:
|
|
6
7
|
files: ["*urls.py", "manage.py", "*settings.py"]
|
|
7
8
|
manifest: ["django"]
|
|
8
9
|
imports: ["from django", "import django"]
|
|
9
|
-
entrypoint_files: ["*urls.py"]
|
|
10
|
+
entrypoint_files: ["*urls.py", "*views.py", "*viewsets.py", "*/views/*.py", "*serializers.py", "*api.py", "*consumers.py"]
|
|
11
|
+
entrypoint_markers: ["APIView", "ViewSet", "@api_view", "@action", "router.register", "path(", "re_path(", "as_view("]
|
|
10
12
|
---
|
|
11
|
-
# Django
|
|
13
|
+
# Django Review Notes
|
|
12
14
|
|
|
13
15
|
## Entrypoints
|
|
14
16
|
- Routes live in `urls.py`: `path()` / `re_path()` map a URL to a view.
|
|
@@ -18,14 +20,14 @@ entrypoint_files: ["*urls.py"]
|
|
|
18
20
|
signals, and middleware.
|
|
19
21
|
|
|
20
22
|
## Authorization / IDOR
|
|
21
|
-
- Auth is enforced by decorators
|
|
23
|
+
- Auth is enforced by decorators such as `@login_required`, DRF permission classes, or
|
|
22
24
|
middleware. Note where it is and where it is missing.
|
|
23
|
-
- Classic IDOR shape: `Model.objects.get(pk=<user input>)`
|
|
25
|
+
- Classic IDOR shape: `Model.objects.get(pk=<user input>)` or `filter(id=...)`
|
|
24
26
|
with no owner/tenant scoping, then returned to the caller. Inspect every object
|
|
25
27
|
fetch keyed by a user-supplied id.
|
|
26
28
|
|
|
27
|
-
## Common
|
|
29
|
+
## Common Sinks / Gotchas
|
|
28
30
|
- SQL: `.raw()`, `.extra()`, `RawSQL`, or string-built SQL via `connection.cursor()`.
|
|
29
31
|
- Templates: `mark_safe`, `|safe`, `format_html` on unescaped user input, autoescape off.
|
|
30
|
-
- `
|
|
31
|
-
a
|
|
32
|
+
- Settings: `DEBUG=True` leaks internals, a hardcoded `SECRET_KEY`. Untrusted
|
|
33
|
+
deserialization is a language-level sink, see the Python guide.
|
|
@@ -7,17 +7,17 @@ detect:
|
|
|
7
7
|
manifest: []
|
|
8
8
|
imports: []
|
|
9
9
|
---
|
|
10
|
-
# Python
|
|
10
|
+
# Python Review Notes
|
|
11
11
|
|
|
12
|
-
Where untrusted input enters
|
|
13
|
-
CLI
|
|
12
|
+
Where untrusted input enters beyond web routes, which the framework guide covers:
|
|
13
|
+
CLI such as `argparse` or `click`, scheduled jobs, queue consumers, and any function fed an
|
|
14
14
|
external value. Non-HTTP sources matter as much as routes:
|
|
15
15
|
|
|
16
16
|
- deserialization: `pickle.loads`, `yaml.load` without `SafeLoader`, `marshal`
|
|
17
17
|
- code execution: `eval`, `exec`, `subprocess(..., shell=True)`, `os.system`
|
|
18
18
|
- XML/XXE: `lxml`/`xml.etree` parsing attacker XML
|
|
19
19
|
- filesystem: `open()` / `os.path.join` on a path built from user input
|
|
20
|
-
- network: `requests.get(user_url)` and
|
|
20
|
+
- network: `requests.get(user_url)` and similar, the SSRF sink.
|
|
21
21
|
|
|
22
22
|
Common sinks: string-built SQL handed to a DB cursor or ORM `.raw()`/`.extra()`,
|
|
23
23
|
a shell command, `eval`/`exec`, a user-controlled file path, a fetch of a
|
|
@@ -7,47 +7,54 @@ PoC, and iterates over multiple rounds with a persistent memory. One round is
|
|
|
7
7
|
roughly 30 minutes. Run as many rounds as needed.
|
|
8
8
|
|
|
9
9
|
Target repository: the directory you were given.
|
|
10
|
-
Workspace: `<workspace>/<project
|
|
10
|
+
Workspace: `<workspace>/<project>/`, created for you, holding `entrypoints/`,
|
|
11
11
|
`issues/`, `analysis/`, and `security-review-memory.md`.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
## On
|
|
15
|
+
## On Start
|
|
16
16
|
|
|
17
17
|
1. Read `security-review-memory.md` in the workspace if it exists:
|
|
18
18
|
- skip every pattern under "Confirmed false positives".
|
|
19
19
|
- do not re-report anything under "Fixed".
|
|
20
20
|
- weight the files under "High-risk areas" more heavily.
|
|
21
|
-
2. Read `entrypoints/_entrypoints.md
|
|
21
|
+
2. Read `entrypoints/_entrypoints.md`, the seeded list of files the detected stack
|
|
22
22
|
flags as likely to define entrypoints. Open them to find the actual
|
|
23
|
-
entrypoints. It is a *starting* subset, not the whole surface
|
|
24
|
-
attack surface"
|
|
25
|
-
3. Read `_stack.md
|
|
26
|
-
notes for them, so you know where this stack's entrypoints
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
entrypoints. It is a *starting* subset, not the whole surface. See "Map the
|
|
24
|
+
attack surface".
|
|
25
|
+
3. Read `_stack.md`, the seeded detected languages, frameworks, and protocols plus
|
|
26
|
+
review notes for them, so you know where this stack's entrypoints and sinks
|
|
27
|
+
live and which protocol checks apply, for example the OAuth checklist. If it
|
|
28
|
+
matched nothing, lean on your own knowledge of the stack.
|
|
29
|
+
4. Read the relevant vulnerability files under the shipped `vulnerabilities/` for
|
|
30
|
+
the target's stack such as sql-injection, idor, ssrf, jwt-validation, or
|
|
31
|
+
insecure-deserialization.
|
|
32
|
+
|
|
33
|
+
## Map the Attack Surface
|
|
34
|
+
|
|
35
|
+
The seeded `entrypoints/_entrypoints.md` flags files that likely define
|
|
36
|
+
entrypoints. It is a starting point, not the whole surface. Before any per-source
|
|
37
|
+
analysis, build a COMPLETE inventory: open every flagged file, read its routes
|
|
38
|
+
and handlers, and enumerate every source the attacker can influence, including
|
|
39
|
+
the ones no scan finds. Untrusted input enters at more than HTTP:
|
|
36
40
|
|
|
37
41
|
- HTTP routes, GraphQL resolvers, gRPC / RPC handlers, WebSocket handlers.
|
|
38
42
|
- CLI commands, scheduled jobs / cron, queue and topic consumers, webhooks and
|
|
39
43
|
third-party callbacks.
|
|
40
|
-
- deserialization points
|
|
41
|
-
|
|
44
|
+
- deserialization points such as pickle, yaml.load, or marshal, file and document parsers
|
|
45
|
+
for XML / XXE, YAML, CSV, zip, image / office, and template rendering of user input.
|
|
42
46
|
- file uploads, archive extraction, and any filesystem path built from user input.
|
|
43
47
|
- headers, cookies, environment, and config read as trusted, and inbound
|
|
44
48
|
inter-service calls.
|
|
45
49
|
|
|
46
50
|
`pickle.loads(cookie)` and `yaml.load(upload)` are entrypoints just as much as a
|
|
47
|
-
route is. Record the inventory in `entrypoints
|
|
48
|
-
auth method
|
|
51
|
+
route is. Record the full inventory in `entrypoints/`, one file per module, each
|
|
52
|
+
listing the source, the auth method, and a review status ✅/⚠️/❌. Do not begin
|
|
53
|
+
per-source analysis until the inventory covers every endpoint, since an endpoint
|
|
54
|
+
you never list is one you never review. This single step is what most decides
|
|
55
|
+
whether the review finds the deep issues.
|
|
49
56
|
|
|
50
|
-
## Analyse
|
|
57
|
+
## Analyse Each Source
|
|
51
58
|
|
|
52
59
|
Read the implementation reachable from each source. For every one ask:
|
|
53
60
|
|
|
@@ -56,22 +63,43 @@ Read the implementation reachable from each source. For every one ask:
|
|
|
56
63
|
a business-state check bypassed or missing?
|
|
57
64
|
- IDOR: can a user reach another user's, tenant's, or service's resource by a
|
|
58
65
|
supplied id?
|
|
59
|
-
- Do privileged operations
|
|
60
|
-
bypass or replay
|
|
66
|
+
- Do privileged operations such as payment, signing, approval, or state change allow state
|
|
67
|
+
bypass or replay with no nonce or time window?
|
|
61
68
|
- Mass assignment: is a user-controlled body bound wholesale into a model?
|
|
62
69
|
- Signature: is a caller-supplied key trusted as the trust anchor?
|
|
63
70
|
|
|
64
|
-
##
|
|
71
|
+
## Authorization Model
|
|
72
|
+
|
|
73
|
+
The missing-authorization and IDOR classes are not local to one function, so they
|
|
74
|
+
need their own pass. This step is language and framework agnostic. The access
|
|
75
|
+
gate looks different per stack, a decorator, a middleware, a permission class, a
|
|
76
|
+
filter, a guard, or an annotation, but every protected endpoint must authenticate
|
|
77
|
+
the caller and authorize the specific resource.
|
|
78
|
+
|
|
79
|
+
First map how this codebase enforces access control, then record on each
|
|
80
|
+
inventory entry which gate it applies and which identity and resource it checks.
|
|
81
|
+
Then hunt three shapes:
|
|
82
|
+
|
|
83
|
+
- A peer that dropped a check. Compare sibling endpoints such as a v1 and a v2, a
|
|
84
|
+
batch and a single, or an admin and a public variant. When one applies an
|
|
85
|
+
ownership or permission check that a sibling omits, the sibling is a likely
|
|
86
|
+
flaw.
|
|
87
|
+
- IDOR. An endpoint acts on a resource named by a client-supplied id with no
|
|
88
|
+
owner or tenant check, however the id arrives.
|
|
89
|
+
- An unauthenticated privileged path. A state-changing or sensitive endpoint is
|
|
90
|
+
reachable without the gate its peers require.
|
|
91
|
+
|
|
92
|
+
## Trace Attack Paths, the Core Work
|
|
65
93
|
|
|
66
94
|
A whole-repo review earns its keep by reasoning *across files*: a flaw is usually
|
|
67
95
|
a source in one file reaching a dangerous sink in another, past a control defined
|
|
68
|
-
in a third
|
|
69
|
-
reaches a query with no ownership check
|
|
96
|
+
in a third, for example a route that trusts a helper which skips signature checks, or an id that
|
|
97
|
+
reaches a query with no ownership check. For each promising source, trace the
|
|
70
98
|
path and record it in `analysis/`:
|
|
71
99
|
|
|
72
100
|
- **Source**: the entrypoint and the attacker-controlled value.
|
|
73
|
-
- **Sink**: the dangerous operation it reaches
|
|
74
|
-
deserialize, template, redirect
|
|
101
|
+
- **Sink**: the dangerous operation it reaches such as a query, shell, file path, fetch,
|
|
102
|
+
deserialize, template, or redirect, with `file:line`.
|
|
75
103
|
- **Controls on the path**: every auth / authz / validation / sanitization /
|
|
76
104
|
signature / tenant check between source and sink, and crucially which are
|
|
77
105
|
missing or bypassable.
|
|
@@ -83,11 +111,11 @@ trace can refer to it instead of restating it.
|
|
|
83
111
|
## Scope
|
|
84
112
|
|
|
85
113
|
Report only HIGH / CRITICAL, exploitable, high-confidence issues. **Do not report**
|
|
86
|
-
|
|
114
|
+
regardless of severity, dependency CVEs, style or best-practice notes,
|
|
87
115
|
speculative issues you cannot tie to a concrete exploit, and risks that only
|
|
88
116
|
matter if production config is leaked.
|
|
89
117
|
|
|
90
|
-
## Recording an
|
|
118
|
+
## Recording an Issue
|
|
91
119
|
|
|
92
120
|
Write one `issues/<name>.md` per confirmed issue. Do not write an issue you cannot
|
|
93
121
|
confirm with high confidence. Each must have:
|
|
@@ -102,7 +130,7 @@ confirm with high confidence. Each must have:
|
|
|
102
130
|
## Analysis
|
|
103
131
|
(cite exact file paths and line numbers)
|
|
104
132
|
|
|
105
|
-
## Attack
|
|
133
|
+
## Attack Path
|
|
106
134
|
(end-to-end, actionable steps)
|
|
107
135
|
|
|
108
136
|
## PoC
|
|
@@ -114,7 +142,7 @@ confirm with high confidence. Each must have:
|
|
|
114
142
|
## Fix
|
|
115
143
|
```
|
|
116
144
|
|
|
117
|
-
## PoC
|
|
145
|
+
## PoC Verification, Human in the Loop
|
|
118
146
|
|
|
119
147
|
Confirm each issue by running the PoC against a sandbox / dev environment. When
|
|
120
148
|
you need something only the operator has, stop and ask:
|
|
@@ -129,11 +157,13 @@ destructive action without the operator's explicit go-ahead.
|
|
|
129
157
|
## Iteration
|
|
130
158
|
|
|
131
159
|
Each round, read the workspace history first and do not repeat finished work.
|
|
132
|
-
Process leftover TODOs, otherwise pick an unreviewed
|
|
133
|
-
|
|
134
|
-
report the
|
|
160
|
+
Process leftover TODOs, otherwise pick an unreviewed ❌ or to-deepen ⚠️ source
|
|
161
|
+
from the inventory. One round rarely finds the deep cross-file and stateful bugs,
|
|
162
|
+
so keep going until two consecutive rounds surface nothing new, then report the
|
|
163
|
+
review complete. The hard classes such as authorization, replay, and broken
|
|
164
|
+
business state usually appear only after several rounds.
|
|
135
165
|
|
|
136
|
-
## On
|
|
166
|
+
## On Finish
|
|
137
167
|
|
|
138
168
|
Append a row to the audit history in `security-review-memory.md`, and ask the
|
|
139
169
|
operator which findings were false positives. Record those under "Confirmed false
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
> updated at the end. It skips confirmed false positives, avoids re-reporting
|
|
5
5
|
> fixed issues, and focuses on historically risky areas.
|
|
6
6
|
|
|
7
|
-
## Confirmed
|
|
7
|
+
## Confirmed False Positives
|
|
8
8
|
|
|
9
9
|
<!-- FP-001 <short description>
|
|
10
10
|
- Date: YYYY-MM-DD
|
|
@@ -13,18 +13,18 @@
|
|
|
13
13
|
- Why not a real issue: <reason>
|
|
14
14
|
-->
|
|
15
15
|
|
|
16
|
-
## Fixed
|
|
16
|
+
## Fixed
|
|
17
17
|
|
|
18
18
|
<!-- FIXED-001 <issue title>
|
|
19
19
|
- Date / commit: YYYY-MM-DD / abc1234
|
|
20
20
|
- Original issue: <summary>
|
|
21
21
|
-->
|
|
22
22
|
|
|
23
|
-
## High-
|
|
23
|
+
## High-Risk Areas
|
|
24
24
|
|
|
25
25
|
<!-- - `<path>`: <reason, for example a past auth bypass> -->
|
|
26
26
|
|
|
27
|
-
## Audit
|
|
27
|
+
## Audit History
|
|
28
28
|
|
|
29
29
|
| Date | Mode | HIGH | MEDIUM | Notes |
|
|
30
30
|
|------|------|------|--------|-------|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: oauth
|
|
3
|
+
title: OAuth and OIDC
|
|
4
|
+
kind: protocol
|
|
5
|
+
detect:
|
|
6
|
+
content: ["grant_type", "authorization_code", "redirect_uri", "code_challenge", "response_type", "client_secret", "openid-configuration"]
|
|
7
|
+
---
|
|
8
|
+
# OAuth and OIDC Review Notes
|
|
9
|
+
|
|
10
|
+
These are protocol invariants, independent of language or framework. The way each
|
|
11
|
+
check looks in code differs by stack, so read the language and framework guides
|
|
12
|
+
for the concrete idioms and confirm each invariant against the actual flow. An
|
|
13
|
+
OAuth or OIDC server holds protocol state, so the high-value bugs are logic,
|
|
14
|
+
authorization, and replay flaws rather than injection.
|
|
15
|
+
|
|
16
|
+
## Authorization Code
|
|
17
|
+
- Single use. The code is redeemable once. The redeem path reads and marks the
|
|
18
|
+
code consumed atomically, under a row lock or an equivalent conditional update,
|
|
19
|
+
so two concurrent requests cannot both succeed. A read then update with no lock
|
|
20
|
+
is a double-redeem.
|
|
21
|
+
- Bound to the client. A code issued to one client is rejected when another
|
|
22
|
+
client presents it. The token step compares the code's client to the
|
|
23
|
+
authenticated client.
|
|
24
|
+
- Bound to the redirect_uri and the PKCE verifier. Both at the token step match
|
|
25
|
+
what was used at authorize. A missing PKCE check on a public client is
|
|
26
|
+
exploitable.
|
|
27
|
+
- Expiry enforced. An expired code is rejected. Confirm the expiry is read and
|
|
28
|
+
compared, not merely stored.
|
|
29
|
+
|
|
30
|
+
## redirect_uri and State
|
|
31
|
+
- redirect_uri is validated against a registered allowlist by exact match, not a
|
|
32
|
+
prefix or a substring, so an open redirect or a code leak is not possible.
|
|
33
|
+
- A state or equivalent anti-forgery value is present and checked, to stop login
|
|
34
|
+
CSRF.
|
|
35
|
+
|
|
36
|
+
## Tokens and Sessions
|
|
37
|
+
- Access and refresh tokens are random, high entropy, scoped, and expiring.
|
|
38
|
+
- Refresh rotates and the previous token is revoked, so a captured refresh cannot
|
|
39
|
+
be replayed.
|
|
40
|
+
- A JWT access token has its signature, algorithm, issuer, audience, and expiry
|
|
41
|
+
verified. Disabling signature verification or allowing an unconstrained
|
|
42
|
+
algorithm is a flaw. See the jwt-validation vulnerability class.
|
|
43
|
+
|
|
44
|
+
## Replay and Signatures
|
|
45
|
+
- A signed or one-time request such as an MFA binding, a webhook, or a privileged
|
|
46
|
+
action carries a nonce or a short timestamp window and a single-use check, so a
|
|
47
|
+
captured request cannot be replayed. See the replay-attack vulnerability class.
|
|
48
|
+
|
|
49
|
+
## Authorization per Endpoint
|
|
50
|
+
- Every token, introspection, revocation, and management endpoint authenticates
|
|
51
|
+
the caller and authorizes the specific resource. Watch for an endpoint that
|
|
52
|
+
acts on a client-supplied id with no owner or tenant check, the IDOR shape, and
|
|
53
|
+
for a privileged endpoint left unauthenticated. See the
|
|
54
|
+
insecure-direct-object-reference and missing-authorization vulnerability classes,
|
|
55
|
+
and the Authorization Model step in the methodology.
|