codejury 0.20.0__tar.gz → 0.22.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.20.0 → codejury-0.22.0}/PKG-INFO +68 -82
- {codejury-0.20.0 → codejury-0.22.0}/README.md +67 -81
- codejury-0.22.0/codejury/__init__.py +15 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/cli.py +33 -25
- codejury-0.20.0/codejury/data/commands/codejury-review.md → codejury-0.22.0/codejury/data/commands/codejury-review-repo.md +2 -2
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/methodologies/repo-review.md +4 -4
- {codejury-0.20.0 → codejury-0.22.0}/codejury/domain/__init__.py +1 -1
- {codejury-0.20.0 → codejury-0.22.0}/codejury/domain/finding.py +1 -1
- {codejury-0.20.0 → codejury-0.22.0}/codejury/json_parse.py +10 -10
- {codejury-0.20.0 → codejury-0.22.0}/codejury/mddoc.py +4 -4
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/openai_format.py +1 -1
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/retry.py +1 -1
- {codejury-0.20.0 → codejury-0.22.0}/codejury/report.py +1 -1
- {codejury-0.20.0 → codejury-0.22.0}/codejury/resources.py +4 -4
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/diff/debate.py +6 -6
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/diff/debate_prompts.py +4 -4
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/diff/engine.py +5 -5
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/diff/findings_filter.py +1 -1
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/diff/prompts.py +1 -1
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/diff/runner.py +6 -6
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/diff/vulnerabilities.py +5 -5
- codejury-0.22.0/codejury/review/repo/__init__.py +0 -0
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/repo/model.py +5 -5
- {codejury-0.20.0/codejury → codejury-0.22.0/codejury/review}/repo/scaffold.py +5 -5
- {codejury-0.20.0 → codejury-0.22.0}/codejury.egg-info/PKG-INFO +68 -82
- {codejury-0.20.0 → codejury-0.22.0}/codejury.egg-info/SOURCES.txt +14 -13
- {codejury-0.20.0 → codejury-0.22.0}/pyproject.toml +2 -2
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_cli_audit.py +11 -9
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_diff_debate.py +2 -2
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_diff_engine.py +6 -6
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_repo_model.py +1 -1
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_repo_scaffold.py +1 -1
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_vulnerabilities.py +3 -3
- codejury-0.20.0/codejury/__init__.py +0 -15
- {codejury-0.20.0 → codejury-0.22.0}/LICENSE +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/__main__.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/detection.yaml +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/frameworks/go/echo.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/frameworks/go/gin.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/frameworks/javascript/express.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/frameworks/javascript/nestjs.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/frameworks/python/celery.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/frameworks/python/django.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/frameworks/python/fastapi.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/frameworks/python/flask.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/languages/go.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/languages/javascript.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/languages/python.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/languages/typescript.md +0 -0
- /codejury-0.20.0/codejury/data/methodologies/security-review-memory.md → /codejury-0.22.0/codejury/data/methodologies/memory-template.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/protocols/oauth.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/SKILL.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/business-logic.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/code-injection.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/command-injection.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/cross-site-request-forgery.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/cross-site-scripting.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/hardcoded-secrets.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/http-response-splitting.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/improper-authentication.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/information-exposure.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/insecure-cryptography.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/insecure-deserialization.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/insecure-direct-object-reference.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/insecure-transport.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/jwt-validation.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/mass-assignment.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/missing-authorization.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/open-redirect.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/path-traversal.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/race-condition.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/replay-attack.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/server-side-request-forgery.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/server-side-template-injection.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/session-fixation.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/sql-injection.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/data/vulnerabilities/xml-external-entity.md +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/detection.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/guides.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/__init__.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/anthropic.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/base.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/factory.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/litellm.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/mock.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury/providers/openai.py +0 -0
- {codejury-0.20.0/codejury/diff → codejury-0.22.0/codejury/review}/__init__.py +0 -0
- {codejury-0.20.0/codejury/repo → codejury-0.22.0/codejury/review/diff}/__init__.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury.egg-info/dependency_links.txt +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury.egg-info/entry_points.txt +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury.egg-info/requires.txt +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/codejury.egg-info/top_level.txt +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/setup.cfg +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_anthropic_provider.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_detection.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_guides.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_json_parse.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_litellm_provider.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_mddoc.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_openai_format.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_openai_provider.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_report.py +0 -0
- {codejury-0.20.0 → codejury-0.22.0}/tests/test_retry_provider.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codejury
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: AI code security review for diffs and
|
|
3
|
+
Version: 0.22.0
|
|
4
|
+
Summary: AI code security review for diffs and repos.
|
|
5
5
|
Author: AISecLabs
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/aiseclabs/codejury
|
|
@@ -38,25 +38,15 @@ Dynamic: license-file
|
|
|
38
38
|
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
An AI code security review tool. It works two ways. `review diff` audits a pull
|
|
42
|
+
request diff for newly introduced exploitable risk in one command. `review repo`
|
|
43
|
+
sets up an interactive agent such as Claude Code or Codex to audit a whole
|
|
44
|
+
repository, mapping the attack surface, tracing inputs to sinks across files, and
|
|
45
|
+
verifying each issue with a real PoC.
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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. One command in, findings out.
|
|
49
|
-
- **Repo Review** is agent driven. A whole repository is too large for one LLM
|
|
50
|
-
call, so codejury scaffolds a workspace and hands an interactive agent such as
|
|
51
|
-
Claude Code or Codex a methodology to run. The agent maps the attack surface,
|
|
52
|
-
traces inputs to sinks across files, verifies issues with a real PoC, and
|
|
53
|
-
iterates over rounds with a persistent memory.
|
|
54
|
-
|
|
55
|
-
Security knowledge is data, not code. Vulnerability classes live in
|
|
56
|
-
`codejury/data/vulnerabilities/*.md` with a vulnerable and a secure example per
|
|
57
|
-
language, and the stack guides live under `data/languages`, `data/frameworks`,
|
|
58
|
-
and `data/protocols`. The engine stays language neutral and names no framework,
|
|
59
|
-
so adding a stack is a drop-in markdown file.
|
|
47
|
+
Security knowledge is data, not code. Drop-in markdown guides hold the
|
|
48
|
+
vulnerability classes, languages, frameworks, and protocols, so the engine names
|
|
49
|
+
no language and adding a stack is a new file.
|
|
60
50
|
|
|
61
51
|
## Install
|
|
62
52
|
|
|
@@ -67,37 +57,80 @@ codejury install-slash-command # Claude Code, ~/.claude/commands/
|
|
|
67
57
|
codejury install-slash-command --agent codex # Codex, ~/.codex/prompts/
|
|
68
58
|
```
|
|
69
59
|
|
|
70
|
-
`install-slash-command` copies the `/codejury-review` command into the
|
|
71
|
-
command directory. The command body is the same for every agent, only the
|
|
72
|
-
directory differs, so pass `--dir` for any other agent.
|
|
73
|
-
agent neutral, so even without the command you can run `codejury review` and
|
|
74
|
-
tell any agent to follow the methodology it writes.
|
|
60
|
+
`install-slash-command` copies the `/codejury-review-repo` command into the
|
|
61
|
+
agent's command directory. The command body is the same for every agent, only the
|
|
62
|
+
directory differs, so pass `--dir` for any other agent.
|
|
75
63
|
|
|
76
64
|
## Diff Review
|
|
77
65
|
|
|
66
|
+
The coded engine. It audits a diff in one command, as a single balanced LLM call
|
|
67
|
+
or an adversarial Finder, Challenger, and Judge pass that trades roughly 3x the
|
|
68
|
+
cost for extra recall on subtle flaws that span files.
|
|
69
|
+
|
|
78
70
|
```bash
|
|
79
|
-
#
|
|
80
|
-
codejury diff --
|
|
71
|
+
# a diff file
|
|
72
|
+
codejury review diff --file changes.diff
|
|
81
73
|
|
|
82
|
-
#
|
|
83
|
-
codejury diff --repo /path/to/app --git-range origin/main...HEAD
|
|
74
|
+
# a git range in a repo
|
|
75
|
+
codejury review diff --repo /path/to/app --git-range origin/main...HEAD
|
|
84
76
|
|
|
85
77
|
# from stdin
|
|
86
|
-
git diff HEAD~1 | codejury diff
|
|
78
|
+
git diff HEAD~1 | codejury review diff
|
|
87
79
|
|
|
88
80
|
# adversarial mode, more recall on subtle flaws, about 3x the cost
|
|
89
|
-
codejury diff --
|
|
81
|
+
codejury review diff --file changes.diff --mode adversarial
|
|
90
82
|
|
|
91
83
|
# CI gate and SARIF
|
|
92
|
-
codejury diff --
|
|
84
|
+
codejury review diff --file changes.diff --format sarif --fail-on high
|
|
93
85
|
```
|
|
94
86
|
|
|
95
87
|
Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
|
|
96
88
|
the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
|
|
97
|
-
variables. `codejury diff --dry-run` exercises the engine with a mock
|
|
89
|
+
variables. `codejury review diff --dry-run` exercises the engine with a mock
|
|
98
90
|
provider and no key, and falls back to a built in demo diff when you pass none.
|
|
99
91
|
|
|
100
|
-
|
|
92
|
+
## Repo Review
|
|
93
|
+
|
|
94
|
+
The agent path. A whole repo is too large for one LLM call, so this sets up a
|
|
95
|
+
review for an interactive agent rather than running a pipeline.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
codejury review repo /path/to/your/repo
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
It detects the stack, seeds the entrypoint inventory and the downstream trace
|
|
102
|
+
targets from a deterministic scan, writes the methodology to
|
|
103
|
+
`<workspace>/METHODOLOGY.md`, and prints a short pointer. The workspace:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
entrypoints/ the candidate entrypoint files to start from
|
|
107
|
+
issues/ one write-up per confirmed or suspected issue
|
|
108
|
+
pocs/ a runnable PoC per issue, same name as the issue
|
|
109
|
+
analysis/ _trace_targets.md, the round ledger, and trace notes
|
|
110
|
+
METHODOLOGY.md and MEMORY.md
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Then run it with an interactive agent. In Claude Code or Codex:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
/codejury-review-repo /path/to/your/repo
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Any agent works, the slash command is just a shortcut. Without it, tell the agent
|
|
120
|
+
to follow the `METHODOLOGY.md` the scaffold wrote. The agent maps the attack
|
|
121
|
+
surface including non HTTP sources, traces each input to its sink through the
|
|
122
|
+
downstream layers, runs an Authorization Model pass for missing-auth and IDOR,
|
|
123
|
+
and follows a control into a library when an entrypoint delegates it. It iterates
|
|
124
|
+
until a Completeness Gate passes, confirms each issue with a real PoC against a
|
|
125
|
+
sandbox or dev environment, and asks you for any credential it needs. Only a
|
|
126
|
+
reproduced PoC is a confirmed finding, and nothing runs against production.
|
|
127
|
+
|
|
128
|
+
The supported stacks today are Python with Django, Celery, Flask, and FastAPI,
|
|
129
|
+
Go with Gin and Echo, JavaScript and TypeScript with Express and NestJS, and the
|
|
130
|
+
OAuth and OIDC protocol. The methodology still works on an unguided stack, it just
|
|
131
|
+
leans more on the agent's own knowledge.
|
|
132
|
+
|
|
133
|
+
## Choosing a Model and Mode
|
|
101
134
|
|
|
102
135
|
Detection quality is dominated by the model first, then the mode. On real diff
|
|
103
136
|
probes:
|
|
@@ -113,7 +146,7 @@ Default to standard mode with a strong model, set with `--model` or
|
|
|
113
146
|
`CODEJURY_MODEL`. False positives are held down by the do not report list and the
|
|
114
147
|
post filter, not by the mode.
|
|
115
148
|
|
|
116
|
-
|
|
149
|
+
## Use in CI with GitHub Actions
|
|
117
150
|
|
|
118
151
|
Audit every pull request and surface findings in the code scanning tab. Copy
|
|
119
152
|
`examples/codejury-pr-review.yml` into `.github/workflows/`, add a
|
|
@@ -127,52 +160,6 @@ The job makes one model call per pull request in standard mode. The SARIF is
|
|
|
127
160
|
uploaded even when the gate fails, so findings always show up on the pull
|
|
128
161
|
request.
|
|
129
162
|
|
|
130
|
-
## Repo Review
|
|
131
|
-
|
|
132
|
-
Repo Review does not scan and print findings. It sets up a review for an agent to
|
|
133
|
-
run, because a whole repository needs many rounds of reading, cross-file tracing,
|
|
134
|
-
and PoC work that an agent does, not a single call.
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
codejury review /path/to/your/repo
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
This detects the stack, seeds the entrypoint inventory and the downstream trace
|
|
141
|
-
targets from a deterministic scan, writes the methodology to
|
|
142
|
-
`<workspace>/METHODOLOGY.md`, and prints a short pointer. It creates the
|
|
143
|
-
workspace:
|
|
144
|
-
|
|
145
|
-
```
|
|
146
|
-
entrypoints/ the candidate entrypoint files to start from
|
|
147
|
-
issues/ one write-up per confirmed or suspected issue
|
|
148
|
-
pocs/ a runnable PoC per issue, same name as the issue
|
|
149
|
-
analysis/ _trace_targets.md, the round ledger, and trace notes
|
|
150
|
-
security-review-memory.md
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Then run it with an interactive agent. In Claude Code or Codex:
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
/codejury-review /path/to/your/repo
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
Any agent works, the slash command is just a shortcut. Without it, tell the agent
|
|
160
|
-
to follow the `METHODOLOGY.md` the scaffold wrote.
|
|
161
|
-
|
|
162
|
-
The agent follows `METHODOLOGY.md`: it maps the attack surface including non HTTP
|
|
163
|
-
sources, traces each input to its sink through the downstream layers, runs an
|
|
164
|
-
Authorization Model pass for missing-auth and IDOR, and follows a control into a
|
|
165
|
-
library when an entrypoint delegates it. It keeps going until a Completeness Gate
|
|
166
|
-
passes, two consecutive rounds that add nothing new. It confirms each issue with
|
|
167
|
-
a real PoC against a sandbox or dev environment and asks you for any credential or
|
|
168
|
-
test data it needs. Only a reproduced PoC is a confirmed finding, and nothing
|
|
169
|
-
runs against production.
|
|
170
|
-
|
|
171
|
-
The supported stacks today are Python with Django, Celery, Flask, and FastAPI,
|
|
172
|
-
Go with Gin and Echo, JavaScript and TypeScript with Express and NestJS, and the
|
|
173
|
-
OAuth and OIDC protocol. The methodology still works on an unguided stack, it just
|
|
174
|
-
leans more on the agent's own knowledge.
|
|
175
|
-
|
|
176
163
|
## Findings
|
|
177
164
|
|
|
178
165
|
Each finding carries a file and line, a severity and category, a concrete exploit
|
|
@@ -194,4 +181,3 @@ change.
|
|
|
194
181
|
entrypoint markers, and downstream logic layers.
|
|
195
182
|
- A protocol such as OAuth: `codejury/data/protocols/<name>.md`, detected by
|
|
196
183
|
language neutral content tokens.
|
|
197
|
-
```
|
|
@@ -7,25 +7,15 @@
|
|
|
7
7
|
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
call, so codejury scaffolds a workspace and hands an interactive agent such as
|
|
20
|
-
Claude Code or Codex a methodology to run. The agent maps the attack surface,
|
|
21
|
-
traces inputs to sinks across files, verifies issues with a real PoC, and
|
|
22
|
-
iterates over rounds with a persistent memory.
|
|
23
|
-
|
|
24
|
-
Security knowledge is data, not code. Vulnerability classes live in
|
|
25
|
-
`codejury/data/vulnerabilities/*.md` with a vulnerable and a secure example per
|
|
26
|
-
language, and the stack guides live under `data/languages`, `data/frameworks`,
|
|
27
|
-
and `data/protocols`. The engine stays language neutral and names no framework,
|
|
28
|
-
so adding a stack is a drop-in markdown file.
|
|
10
|
+
An AI code security review tool. It works two ways. `review diff` audits a pull
|
|
11
|
+
request diff for newly introduced exploitable risk in one command. `review repo`
|
|
12
|
+
sets up an interactive agent such as Claude Code or Codex to audit a whole
|
|
13
|
+
repository, mapping the attack surface, tracing inputs to sinks across files, and
|
|
14
|
+
verifying each issue with a real PoC.
|
|
15
|
+
|
|
16
|
+
Security knowledge is data, not code. Drop-in markdown guides hold the
|
|
17
|
+
vulnerability classes, languages, frameworks, and protocols, so the engine names
|
|
18
|
+
no language and adding a stack is a new file.
|
|
29
19
|
|
|
30
20
|
## Install
|
|
31
21
|
|
|
@@ -36,37 +26,80 @@ codejury install-slash-command # Claude Code, ~/.claude/commands/
|
|
|
36
26
|
codejury install-slash-command --agent codex # Codex, ~/.codex/prompts/
|
|
37
27
|
```
|
|
38
28
|
|
|
39
|
-
`install-slash-command` copies the `/codejury-review` command into the
|
|
40
|
-
command directory. The command body is the same for every agent, only the
|
|
41
|
-
directory differs, so pass `--dir` for any other agent.
|
|
42
|
-
agent neutral, so even without the command you can run `codejury review` and
|
|
43
|
-
tell any agent to follow the methodology it writes.
|
|
29
|
+
`install-slash-command` copies the `/codejury-review-repo` command into the
|
|
30
|
+
agent's command directory. The command body is the same for every agent, only the
|
|
31
|
+
directory differs, so pass `--dir` for any other agent.
|
|
44
32
|
|
|
45
33
|
## Diff Review
|
|
46
34
|
|
|
35
|
+
The coded engine. It audits a diff in one command, as a single balanced LLM call
|
|
36
|
+
or an adversarial Finder, Challenger, and Judge pass that trades roughly 3x the
|
|
37
|
+
cost for extra recall on subtle flaws that span files.
|
|
38
|
+
|
|
47
39
|
```bash
|
|
48
|
-
#
|
|
49
|
-
codejury diff --
|
|
40
|
+
# a diff file
|
|
41
|
+
codejury review diff --file changes.diff
|
|
50
42
|
|
|
51
|
-
#
|
|
52
|
-
codejury diff --repo /path/to/app --git-range origin/main...HEAD
|
|
43
|
+
# a git range in a repo
|
|
44
|
+
codejury review diff --repo /path/to/app --git-range origin/main...HEAD
|
|
53
45
|
|
|
54
46
|
# from stdin
|
|
55
|
-
git diff HEAD~1 | codejury diff
|
|
47
|
+
git diff HEAD~1 | codejury review diff
|
|
56
48
|
|
|
57
49
|
# adversarial mode, more recall on subtle flaws, about 3x the cost
|
|
58
|
-
codejury diff --
|
|
50
|
+
codejury review diff --file changes.diff --mode adversarial
|
|
59
51
|
|
|
60
52
|
# CI gate and SARIF
|
|
61
|
-
codejury diff --
|
|
53
|
+
codejury review diff --file changes.diff --format sarif --fail-on high
|
|
62
54
|
```
|
|
63
55
|
|
|
64
56
|
Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
|
|
65
57
|
the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
|
|
66
|
-
variables. `codejury diff --dry-run` exercises the engine with a mock
|
|
58
|
+
variables. `codejury review diff --dry-run` exercises the engine with a mock
|
|
67
59
|
provider and no key, and falls back to a built in demo diff when you pass none.
|
|
68
60
|
|
|
69
|
-
|
|
61
|
+
## Repo Review
|
|
62
|
+
|
|
63
|
+
The agent path. A whole repo is too large for one LLM call, so this sets up a
|
|
64
|
+
review for an interactive agent rather than running a pipeline.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
codejury review repo /path/to/your/repo
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
It detects the stack, seeds the entrypoint inventory and the downstream trace
|
|
71
|
+
targets from a deterministic scan, writes the methodology to
|
|
72
|
+
`<workspace>/METHODOLOGY.md`, and prints a short pointer. The workspace:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
entrypoints/ the candidate entrypoint files to start from
|
|
76
|
+
issues/ one write-up per confirmed or suspected issue
|
|
77
|
+
pocs/ a runnable PoC per issue, same name as the issue
|
|
78
|
+
analysis/ _trace_targets.md, the round ledger, and trace notes
|
|
79
|
+
METHODOLOGY.md and MEMORY.md
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Then run it with an interactive agent. In Claude Code or Codex:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
/codejury-review-repo /path/to/your/repo
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Any agent works, the slash command is just a shortcut. Without it, tell the agent
|
|
89
|
+
to follow the `METHODOLOGY.md` the scaffold wrote. The agent maps the attack
|
|
90
|
+
surface including non HTTP sources, traces each input to its sink through the
|
|
91
|
+
downstream layers, runs an Authorization Model pass for missing-auth and IDOR,
|
|
92
|
+
and follows a control into a library when an entrypoint delegates it. It iterates
|
|
93
|
+
until a Completeness Gate passes, confirms each issue with a real PoC against a
|
|
94
|
+
sandbox or dev environment, and asks you for any credential it needs. Only a
|
|
95
|
+
reproduced PoC is a confirmed finding, and nothing runs against production.
|
|
96
|
+
|
|
97
|
+
The supported stacks today are Python with Django, Celery, Flask, and FastAPI,
|
|
98
|
+
Go with Gin and Echo, JavaScript and TypeScript with Express and NestJS, and the
|
|
99
|
+
OAuth and OIDC protocol. The methodology still works on an unguided stack, it just
|
|
100
|
+
leans more on the agent's own knowledge.
|
|
101
|
+
|
|
102
|
+
## Choosing a Model and Mode
|
|
70
103
|
|
|
71
104
|
Detection quality is dominated by the model first, then the mode. On real diff
|
|
72
105
|
probes:
|
|
@@ -82,7 +115,7 @@ Default to standard mode with a strong model, set with `--model` or
|
|
|
82
115
|
`CODEJURY_MODEL`. False positives are held down by the do not report list and the
|
|
83
116
|
post filter, not by the mode.
|
|
84
117
|
|
|
85
|
-
|
|
118
|
+
## Use in CI with GitHub Actions
|
|
86
119
|
|
|
87
120
|
Audit every pull request and surface findings in the code scanning tab. Copy
|
|
88
121
|
`examples/codejury-pr-review.yml` into `.github/workflows/`, add a
|
|
@@ -96,52 +129,6 @@ The job makes one model call per pull request in standard mode. The SARIF is
|
|
|
96
129
|
uploaded even when the gate fails, so findings always show up on the pull
|
|
97
130
|
request.
|
|
98
131
|
|
|
99
|
-
## Repo Review
|
|
100
|
-
|
|
101
|
-
Repo Review does not scan and print findings. It sets up a review for an agent to
|
|
102
|
-
run, because a whole repository needs many rounds of reading, cross-file tracing,
|
|
103
|
-
and PoC work that an agent does, not a single call.
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
codejury review /path/to/your/repo
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
This detects the stack, seeds the entrypoint inventory and the downstream trace
|
|
110
|
-
targets from a deterministic scan, writes the methodology to
|
|
111
|
-
`<workspace>/METHODOLOGY.md`, and prints a short pointer. It creates the
|
|
112
|
-
workspace:
|
|
113
|
-
|
|
114
|
-
```
|
|
115
|
-
entrypoints/ the candidate entrypoint files to start from
|
|
116
|
-
issues/ one write-up per confirmed or suspected issue
|
|
117
|
-
pocs/ a runnable PoC per issue, same name as the issue
|
|
118
|
-
analysis/ _trace_targets.md, the round ledger, and trace notes
|
|
119
|
-
security-review-memory.md
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Then run it with an interactive agent. In Claude Code or Codex:
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
/codejury-review /path/to/your/repo
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
Any agent works, the slash command is just a shortcut. Without it, tell the agent
|
|
129
|
-
to follow the `METHODOLOGY.md` the scaffold wrote.
|
|
130
|
-
|
|
131
|
-
The agent follows `METHODOLOGY.md`: it maps the attack surface including non HTTP
|
|
132
|
-
sources, traces each input to its sink through the downstream layers, runs an
|
|
133
|
-
Authorization Model pass for missing-auth and IDOR, and follows a control into a
|
|
134
|
-
library when an entrypoint delegates it. It keeps going until a Completeness Gate
|
|
135
|
-
passes, two consecutive rounds that add nothing new. It confirms each issue with
|
|
136
|
-
a real PoC against a sandbox or dev environment and asks you for any credential or
|
|
137
|
-
test data it needs. Only a reproduced PoC is a confirmed finding, and nothing
|
|
138
|
-
runs against production.
|
|
139
|
-
|
|
140
|
-
The supported stacks today are Python with Django, Celery, Flask, and FastAPI,
|
|
141
|
-
Go with Gin and Echo, JavaScript and TypeScript with Express and NestJS, and the
|
|
142
|
-
OAuth and OIDC protocol. The methodology still works on an unguided stack, it just
|
|
143
|
-
leans more on the agent's own knowledge.
|
|
144
|
-
|
|
145
132
|
## Findings
|
|
146
133
|
|
|
147
134
|
Each finding carries a file and line, a severity and category, a concrete exploit
|
|
@@ -163,4 +150,3 @@ change.
|
|
|
163
150
|
entrypoint markers, and downstream logic layers.
|
|
164
151
|
- A protocol such as OAuth: `codejury/data/protocols/<name>.md`, detected by
|
|
165
152
|
language neutral content tokens.
|
|
166
|
-
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""AI code security review tool.
|
|
2
|
+
|
|
3
|
+
Two paths matched to their nature: a coded diff-audit engine, a standard single
|
|
4
|
+
call or an adversarial Finder/Challenger/Judge pass, and a whole-repo review run
|
|
5
|
+
as a methodology by an interactive agent. Security knowledge lives in rich
|
|
6
|
+
markdown vulnerability classes under data/vulnerabilities, injected into the
|
|
7
|
+
audit prompt, not in a rendered schema.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
__version__ = version("codejury")
|
|
14
|
+
except PackageNotFoundError: # running from a source tree without an install
|
|
15
|
+
__version__ = "0.0.0"
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Two paths matched to their nature:
|
|
4
4
|
|
|
5
|
-
- ``diff`` runs the coded diff engine over a unified diff: a single
|
|
6
|
-
|
|
7
|
-
- ``review <dir>`` scaffolds a workspace and prints the methodology for an
|
|
8
|
-
interactive agent to run a whole-repo review
|
|
9
|
-
which a single call cannot do for a whole codebase
|
|
10
|
-
|
|
11
|
-
``diff --dry-run`` exercises the engine with a mock provider and no key.
|
|
12
|
-
The audit orchestration itself lives in ``codejury.diff.runner``.
|
|
5
|
+
- ``review diff`` runs the coded diff engine over a unified diff: a single
|
|
6
|
+
balanced call in standard mode or the adversarial Finder/Challenger/Judge pass.
|
|
7
|
+
- ``review repo <dir>`` scaffolds a workspace and prints the methodology for an
|
|
8
|
+
interactive agent to run a whole-repo review. It does not run an LLM pipeline,
|
|
9
|
+
which a single call cannot do for a whole codebase.
|
|
10
|
+
|
|
11
|
+
``review diff --dry-run`` exercises the engine with a mock provider and no key.
|
|
12
|
+
The audit orchestration itself lives in ``codejury.review.diff.runner``.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
@@ -21,7 +21,7 @@ from pathlib import Path
|
|
|
21
21
|
|
|
22
22
|
from codejury import __version__
|
|
23
23
|
from codejury.report import gate, render
|
|
24
|
-
from codejury.diff.runner import audit_diff
|
|
24
|
+
from codejury.review.diff.runner import audit_diff
|
|
25
25
|
from codejury.providers.factory import (
|
|
26
26
|
DEFAULT_API_BASE,
|
|
27
27
|
DEFAULT_API_KEY,
|
|
@@ -33,15 +33,15 @@ from codejury.providers.factory import (
|
|
|
33
33
|
make_provider,
|
|
34
34
|
)
|
|
35
35
|
from codejury.providers.mock import MockProvider
|
|
36
|
-
from codejury.repo.scaffold import scaffold
|
|
36
|
+
from codejury.review.repo.scaffold import scaffold
|
|
37
37
|
|
|
38
38
|
_FORMATS = ("text", "markdown", "json", "sarif")
|
|
39
39
|
_FAIL_ON = ("critical", "high", "medium", "low")
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
def _read_diff(args) -> str:
|
|
43
|
-
if args.
|
|
44
|
-
with open(args.
|
|
43
|
+
if args.file:
|
|
44
|
+
with open(args.file, encoding="utf-8") as f:
|
|
45
45
|
return f.read()
|
|
46
46
|
if args.git_range:
|
|
47
47
|
return subprocess.run(
|
|
@@ -66,7 +66,7 @@ _MOCK_REPLY = (
|
|
|
66
66
|
|
|
67
67
|
def _add_audit_args(p) -> None:
|
|
68
68
|
"""The diff-audit flags for `review diff`."""
|
|
69
|
-
p.add_argument("--
|
|
69
|
+
p.add_argument("--file", default=None, help="unified diff file (default: read stdin)")
|
|
70
70
|
p.add_argument("--repo", default=None, help="repo path for --git-range")
|
|
71
71
|
p.add_argument("--git-range", default=None, help="git range to diff, e.g. origin/main...HEAD")
|
|
72
72
|
p.add_argument("--dry-run", action="store_true",
|
|
@@ -93,14 +93,15 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
93
93
|
parser.add_argument("--version", action="version", version=f"codejury {__version__}")
|
|
94
94
|
sub = parser.add_subparsers(dest="command")
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
review = sub.add_parser("review", help="review code for security findings")
|
|
97
|
+
rsub = review.add_subparsers(dest="scope")
|
|
98
|
+
_add_audit_args(rsub.add_parser("diff", help="audit a unified diff (the coded engine)"))
|
|
99
|
+
repo = rsub.add_parser("repo", help="scaffold a whole-repo review for an interactive agent")
|
|
100
|
+
repo.add_argument("directory", help="target repository to review")
|
|
101
|
+
repo.add_argument("--workspace", default="codejury-review", help="where to create the review workspace")
|
|
101
102
|
|
|
102
103
|
inst = sub.add_parser("install-slash-command",
|
|
103
|
-
help="install the /codejury-review slash command for an agent")
|
|
104
|
+
help="install the /codejury-review-repo slash command for an agent")
|
|
104
105
|
inst.add_argument("--agent", choices=("claude", "codex"), default="claude",
|
|
105
106
|
help="which agent's command directory to install into")
|
|
106
107
|
inst.add_argument("--dir", default=None, help="explicit target directory, overrides --agent")
|
|
@@ -115,12 +116,13 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
115
116
|
|
|
116
117
|
|
|
117
118
|
def _dispatch(args, parser) -> int:
|
|
118
|
-
|
|
119
|
+
scope = getattr(args, "scope", None)
|
|
120
|
+
if args.command == "review" and scope == "diff":
|
|
119
121
|
if args.dry_run:
|
|
120
122
|
provider = MockProvider(default=_MOCK_REPLY)
|
|
121
123
|
model = "mock"
|
|
122
124
|
# zero-config smoke test: fall back to a built-in demo diff when none is supplied
|
|
123
|
-
diff = _read_diff(args) if (args.
|
|
125
|
+
diff = _read_diff(args) if (args.file or args.git_range) else _dry_run_diff()
|
|
124
126
|
else:
|
|
125
127
|
provider = make_provider(args.provider, api_key=args.api_key, api_base=args.api_base, retries=args.retries)
|
|
126
128
|
model = args.model
|
|
@@ -134,7 +136,7 @@ def _dispatch(args, parser) -> int:
|
|
|
134
136
|
print(render(args.fmt, kept))
|
|
135
137
|
return 1 if gate(kept, args.fail_on) else 0
|
|
136
138
|
|
|
137
|
-
if args.command == "review":
|
|
139
|
+
if args.command == "review" and scope == "repo":
|
|
138
140
|
res = scaffold(args.directory, args.workspace)
|
|
139
141
|
(Path(res.workspace) / "METHODOLOGY.md").write_text(res.methodology, encoding="utf-8")
|
|
140
142
|
print(f"Workspace ready: {res.workspace}", file=sys.stderr)
|
|
@@ -146,7 +148,7 @@ def _dispatch(args, parser) -> int:
|
|
|
146
148
|
print(
|
|
147
149
|
"This command sets up the review, it does not find the issues itself. Next, have an "
|
|
148
150
|
f"interactive agent follow {res.workspace}/METHODOLOGY.md to run the review, or use the "
|
|
149
|
-
"/codejury-review command in Claude Code or Codex. Findings are written to "
|
|
151
|
+
"/codejury-review-repo command in Claude Code or Codex. Findings are written to "
|
|
150
152
|
f"{res.workspace}/issues/."
|
|
151
153
|
)
|
|
152
154
|
return 0
|
|
@@ -160,13 +162,19 @@ def _dispatch(args, parser) -> int:
|
|
|
160
162
|
}
|
|
161
163
|
target_dir = Path(args.dir) if args.dir else agent_dirs[args.agent]
|
|
162
164
|
target_dir.mkdir(parents=True, exist_ok=True)
|
|
163
|
-
name = "codejury-review.md"
|
|
165
|
+
name = "codejury-review-repo.md"
|
|
164
166
|
dst = target_dir / name
|
|
165
167
|
dst.write_text((COMMANDS_DIR / name).read_text(encoding="utf-8"), encoding="utf-8")
|
|
166
168
|
print(f"Installed slash command to {dst}")
|
|
167
|
-
print("Run it in the agent with: /codejury-review <repository>")
|
|
169
|
+
print("Run it in the agent with: /codejury-review-repo <repository>")
|
|
168
170
|
return 0
|
|
169
171
|
|
|
172
|
+
if args.command == "review": # no scope given
|
|
173
|
+
print("usage: codejury review {diff,repo} ...", file=sys.stderr)
|
|
174
|
+
print(" diff audit a unified diff for security findings", file=sys.stderr)
|
|
175
|
+
print(" repo scaffold a whole-repo review for an interactive agent", file=sys.stderr)
|
|
176
|
+
return 1
|
|
177
|
+
|
|
170
178
|
parser.print_help()
|
|
171
179
|
return 1
|
|
172
180
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Run a codejury whole-repo security review on a repository, interactively
|
|
3
3
|
---
|
|
4
|
-
Run a codejury whole-
|
|
4
|
+
Run a codejury whole-repo security review of: $ARGUMENTS
|
|
5
5
|
|
|
6
6
|
1. Scaffold the workspace:
|
|
7
7
|
|
|
8
8
|
```
|
|
9
|
-
codejury review $ARGUMENTS --workspace /tmp/codejury-review
|
|
9
|
+
codejury review repo $ARGUMENTS --workspace /tmp/codejury-review
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
If `codejury` is not on PATH it is a pip-installed console script, so activate
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Repo Security Review: Agent Methodology
|
|
2
2
|
|
|
3
|
-
The `review repo` path: a whole-
|
|
3
|
+
The `review repo` path: a whole-repo security audit, run by an interactive
|
|
4
4
|
coding agent such as Claude Code or Codex, not a one-shot LLM call. It maps the
|
|
5
5
|
attack surface, traces inputs to sinks across files, verifies issues with a real
|
|
6
6
|
PoC, and iterates over multiple rounds with a persistent memory. One round is
|
|
@@ -8,13 +8,13 @@ roughly 30 minutes. Run as many rounds as needed.
|
|
|
8
8
|
|
|
9
9
|
Target repository: the directory you were given.
|
|
10
10
|
Workspace: `<workspace>/<project>/`, created for you, holding `entrypoints/`,
|
|
11
|
-
`issues/`, `analysis/`, and `
|
|
11
|
+
`issues/`, `analysis/`, and `MEMORY.md`.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
## On Start
|
|
16
16
|
|
|
17
|
-
1. Read `
|
|
17
|
+
1. Read `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.
|
|
@@ -226,6 +226,6 @@ If any item fails, run another round. State which items pass when you report.
|
|
|
226
226
|
|
|
227
227
|
Report the confirmed findings, the ones with a reproduced PoC, separately from
|
|
228
228
|
the suspected ones still blocked on verification, so the two are never conflated.
|
|
229
|
-
Append a row to the audit history in `
|
|
229
|
+
Append a row to the audit history in `MEMORY.md`, and ask the
|
|
230
230
|
operator which findings were false positives. Record those under "Confirmed false
|
|
231
231
|
positives" so future rounds skip them.
|
|
@@ -45,7 +45,7 @@ def _to_line(value: object) -> int | None:
|
|
|
45
45
|
|
|
46
46
|
def finding_from_dict(data: dict[str, Any]) -> Finding | None:
|
|
47
47
|
"""Map one loosely-typed model finding onto a Finding, or None if it has no
|
|
48
|
-
location
|
|
48
|
+
location, since every finding carries a file, that is the invariant."""
|
|
49
49
|
if not isinstance(data, dict):
|
|
50
50
|
return None
|
|
51
51
|
file = str(data.get("file", "")).strip()
|