codejury 0.19.0__tar.gz → 0.20.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.
Files changed (102) hide show
  1. {codejury-0.19.0 → codejury-0.20.0}/PKG-INFO +83 -33
  2. codejury-0.20.0/README.md +166 -0
  3. codejury-0.20.0/codejury/__main__.py +10 -0
  4. {codejury-0.19.0 → codejury-0.20.0}/codejury/cli.py +43 -23
  5. codejury-0.20.0/codejury/data/commands/codejury-review.md +29 -0
  6. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/detection.yaml +1 -1
  7. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/methodologies/repo-review.md +7 -5
  8. {codejury-0.19.0 → codejury-0.20.0}/codejury/repo/scaffold.py +1 -1
  9. {codejury-0.19.0 → codejury-0.20.0}/codejury/resources.py +1 -0
  10. {codejury-0.19.0 → codejury-0.20.0}/codejury.egg-info/PKG-INFO +83 -33
  11. {codejury-0.19.0 → codejury-0.20.0}/codejury.egg-info/SOURCES.txt +2 -0
  12. {codejury-0.19.0 → codejury-0.20.0}/pyproject.toml +2 -2
  13. {codejury-0.19.0 → codejury-0.20.0}/tests/test_cli_audit.py +26 -2
  14. {codejury-0.19.0 → codejury-0.20.0}/tests/test_repo_model.py +3 -0
  15. {codejury-0.19.0 → codejury-0.20.0}/tests/test_repo_scaffold.py +1 -1
  16. codejury-0.19.0/README.md +0 -116
  17. {codejury-0.19.0 → codejury-0.20.0}/LICENSE +0 -0
  18. {codejury-0.19.0 → codejury-0.20.0}/codejury/__init__.py +0 -0
  19. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/frameworks/go/echo.md +0 -0
  20. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/frameworks/go/gin.md +0 -0
  21. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/frameworks/javascript/express.md +0 -0
  22. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/frameworks/javascript/nestjs.md +0 -0
  23. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/frameworks/python/celery.md +0 -0
  24. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/frameworks/python/django.md +0 -0
  25. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/frameworks/python/fastapi.md +0 -0
  26. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/frameworks/python/flask.md +0 -0
  27. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/languages/go.md +0 -0
  28. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/languages/javascript.md +0 -0
  29. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/languages/python.md +0 -0
  30. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/languages/typescript.md +0 -0
  31. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/methodologies/security-review-memory.md +0 -0
  32. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/protocols/oauth.md +0 -0
  33. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/SKILL.md +0 -0
  34. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/business-logic.md +0 -0
  35. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/code-injection.md +0 -0
  36. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/command-injection.md +0 -0
  37. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/cross-site-request-forgery.md +0 -0
  38. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/cross-site-scripting.md +0 -0
  39. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/hardcoded-secrets.md +0 -0
  40. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/http-response-splitting.md +0 -0
  41. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/improper-authentication.md +0 -0
  42. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/information-exposure.md +0 -0
  43. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/insecure-cryptography.md +0 -0
  44. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/insecure-deserialization.md +0 -0
  45. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/insecure-direct-object-reference.md +0 -0
  46. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/insecure-transport.md +0 -0
  47. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/jwt-validation.md +0 -0
  48. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/mass-assignment.md +0 -0
  49. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/missing-authorization.md +0 -0
  50. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/open-redirect.md +0 -0
  51. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/path-traversal.md +0 -0
  52. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/race-condition.md +0 -0
  53. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/replay-attack.md +0 -0
  54. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/server-side-request-forgery.md +0 -0
  55. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/server-side-template-injection.md +0 -0
  56. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/session-fixation.md +0 -0
  57. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/sql-injection.md +0 -0
  58. {codejury-0.19.0 → codejury-0.20.0}/codejury/data/vulnerabilities/xml-external-entity.md +0 -0
  59. {codejury-0.19.0 → codejury-0.20.0}/codejury/detection.py +0 -0
  60. {codejury-0.19.0 → codejury-0.20.0}/codejury/diff/__init__.py +0 -0
  61. {codejury-0.19.0 → codejury-0.20.0}/codejury/diff/debate.py +0 -0
  62. {codejury-0.19.0 → codejury-0.20.0}/codejury/diff/debate_prompts.py +0 -0
  63. {codejury-0.19.0 → codejury-0.20.0}/codejury/diff/engine.py +0 -0
  64. {codejury-0.19.0 → codejury-0.20.0}/codejury/diff/findings_filter.py +0 -0
  65. {codejury-0.19.0 → codejury-0.20.0}/codejury/diff/prompts.py +0 -0
  66. {codejury-0.19.0 → codejury-0.20.0}/codejury/diff/runner.py +0 -0
  67. {codejury-0.19.0 → codejury-0.20.0}/codejury/diff/vulnerabilities.py +0 -0
  68. {codejury-0.19.0 → codejury-0.20.0}/codejury/domain/__init__.py +0 -0
  69. {codejury-0.19.0 → codejury-0.20.0}/codejury/domain/finding.py +0 -0
  70. {codejury-0.19.0 → codejury-0.20.0}/codejury/guides.py +0 -0
  71. {codejury-0.19.0 → codejury-0.20.0}/codejury/json_parse.py +0 -0
  72. {codejury-0.19.0 → codejury-0.20.0}/codejury/mddoc.py +0 -0
  73. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/__init__.py +0 -0
  74. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/anthropic.py +0 -0
  75. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/base.py +0 -0
  76. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/factory.py +0 -0
  77. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/litellm.py +0 -0
  78. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/mock.py +0 -0
  79. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/openai.py +0 -0
  80. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/openai_format.py +0 -0
  81. {codejury-0.19.0 → codejury-0.20.0}/codejury/providers/retry.py +0 -0
  82. {codejury-0.19.0 → codejury-0.20.0}/codejury/repo/__init__.py +0 -0
  83. {codejury-0.19.0 → codejury-0.20.0}/codejury/repo/model.py +0 -0
  84. {codejury-0.19.0 → codejury-0.20.0}/codejury/report.py +0 -0
  85. {codejury-0.19.0 → codejury-0.20.0}/codejury.egg-info/dependency_links.txt +0 -0
  86. {codejury-0.19.0 → codejury-0.20.0}/codejury.egg-info/entry_points.txt +0 -0
  87. {codejury-0.19.0 → codejury-0.20.0}/codejury.egg-info/requires.txt +0 -0
  88. {codejury-0.19.0 → codejury-0.20.0}/codejury.egg-info/top_level.txt +0 -0
  89. {codejury-0.19.0 → codejury-0.20.0}/setup.cfg +0 -0
  90. {codejury-0.19.0 → codejury-0.20.0}/tests/test_anthropic_provider.py +0 -0
  91. {codejury-0.19.0 → codejury-0.20.0}/tests/test_detection.py +0 -0
  92. {codejury-0.19.0 → codejury-0.20.0}/tests/test_diff_debate.py +0 -0
  93. {codejury-0.19.0 → codejury-0.20.0}/tests/test_diff_engine.py +0 -0
  94. {codejury-0.19.0 → codejury-0.20.0}/tests/test_guides.py +0 -0
  95. {codejury-0.19.0 → codejury-0.20.0}/tests/test_json_parse.py +0 -0
  96. {codejury-0.19.0 → codejury-0.20.0}/tests/test_litellm_provider.py +0 -0
  97. {codejury-0.19.0 → codejury-0.20.0}/tests/test_mddoc.py +0 -0
  98. {codejury-0.19.0 → codejury-0.20.0}/tests/test_openai_format.py +0 -0
  99. {codejury-0.19.0 → codejury-0.20.0}/tests/test_openai_provider.py +0 -0
  100. {codejury-0.19.0 → codejury-0.20.0}/tests/test_report.py +0 -0
  101. {codejury-0.19.0 → codejury-0.20.0}/tests/test_retry_provider.py +0 -0
  102. {codejury-0.19.0 → codejury-0.20.0}/tests/test_vulnerabilities.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codejury
3
- Version: 0.19.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
3
+ Version: 0.20.0
4
+ Summary: AI code security review for diffs and whole repositories.
5
5
  Author: AISecLabs
6
6
  License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/aiseclabs/codejury
@@ -40,52 +40,61 @@ Dynamic: license-file
40
40
 
41
41
  > AI code security review for diffs and whole repositories.
42
42
 
43
- It runs two paths matched to their nature.
43
+ codejury runs two paths matched to their nature.
44
44
 
45
45
  - **Diff Review** is coded. It audits a pull request diff for newly introduced
46
46
  exploitable risk, as a single balanced LLM call or an adversarial Finder,
47
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.
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.
59
60
 
60
61
  ## Install
61
62
 
62
63
  ```bash
63
- pip install codejury # core
64
- pip install "codejury[anthropic]" # add a backend, also openai or litellm
64
+ pip install codejury # core
65
+ pip install "codejury[anthropic]" # add a backend, also openai or litellm
66
+ codejury install-slash-command # Claude Code, ~/.claude/commands/
67
+ codejury install-slash-command --agent codex # Codex, ~/.codex/prompts/
65
68
  ```
66
69
 
70
+ `install-slash-command` copies the `/codejury-review` command into the agent's
71
+ command directory. The command body is the same for every agent, only the
72
+ directory differs, so pass `--dir` for any other agent. The repo review itself is
73
+ agent neutral, so even without the command you can run `codejury review` and
74
+ tell any agent to follow the methodology it writes.
75
+
67
76
  ## Diff Review
68
77
 
69
78
  ```bash
70
79
  # audit a diff file
71
- codejury review diff --diff-file changes.diff
80
+ codejury diff --diff-file changes.diff
72
81
 
73
82
  # audit a git range in a repo
74
- codejury review diff --repo /path/to/app --git-range origin/main...HEAD
83
+ codejury diff --repo /path/to/app --git-range origin/main...HEAD
75
84
 
76
85
  # from stdin
77
- git diff HEAD~1 | codejury review diff
86
+ git diff HEAD~1 | codejury diff
78
87
 
79
88
  # adversarial mode, more recall on subtle flaws, about 3x the cost
80
- codejury review diff --diff-file changes.diff --mode adversarial
89
+ codejury diff --diff-file changes.diff --mode adversarial
81
90
 
82
91
  # CI gate and SARIF
83
- codejury review diff --diff-file changes.diff --format sarif --fail-on high
92
+ codejury diff --diff-file changes.diff --format sarif --fail-on high
84
93
  ```
85
94
 
86
95
  Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
87
96
  the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
88
- variables. `codejury review diff --dry-run` exercises the engine with a mock
97
+ variables. `codejury diff --dry-run` exercises the engine with a mock
89
98
  provider and no key, and falls back to a built in demo diff when you pass none.
90
99
 
91
100
  ### Choosing a Model and Mode
@@ -120,17 +129,49 @@ request.
120
129
 
121
130
  ## Repo Review
122
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
+
123
136
  ```bash
124
- codejury review repo /path/to/your/repo
137
+ codejury review /path/to/your/repo
125
138
  ```
126
139
 
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.
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.
134
175
 
135
176
  ## Findings
136
177
 
@@ -142,6 +183,15 @@ production config leaks.
142
183
 
143
184
  ## Extending
144
185
 
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.
186
+ Knowledge is data, so extending codejury is a drop-in markdown file with no code
187
+ change.
188
+
189
+ - A vulnerability class: `codejury/data/vulnerabilities/<class>.md` with
190
+ frontmatter of title, impact, tags, and triggers, plus a vulnerable and a
191
+ secure example.
192
+ - A language or framework: `codejury/data/languages/<lang>.md` or
193
+ `codejury/data/frameworks/<lang>/<framework>.md`, declaring its detect signals,
194
+ entrypoint markers, and downstream logic layers.
195
+ - A protocol such as OAuth: `codejury/data/protocols/<name>.md`, detected by
196
+ language neutral content tokens.
197
+ ```
@@ -0,0 +1,166 @@
1
+ ```
2
+ ██████╗ ██████╗ ██████╗ ███████╗ ██╗██╗ ██╗██████╗ ██╗ ██╗
3
+ ██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██║██║ ██║██╔══██╗╚██╗ ██╔╝
4
+ ██║ ██║ ██║██║ ██║█████╗ ██║██║ ██║██████╔╝ ╚████╔╝
5
+ ██║ ██║ ██║██║ ██║██╔══╝ ██ ██║██║ ██║██╔══██╗ ╚██╔╝
6
+ ╚██████╗╚██████╔╝██████╔╝███████╗╚█████╔╝╚██████╔╝██║ ██║ ██║
7
+ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
8
+ ```
9
+
10
+ > AI code security review for diffs and whole repositories.
11
+
12
+ codejury 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. One command in, findings out.
18
+ - **Repo Review** is agent driven. A whole repository is too large for one LLM
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.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install codejury # core
34
+ pip install "codejury[anthropic]" # add a backend, also openai or litellm
35
+ codejury install-slash-command # Claude Code, ~/.claude/commands/
36
+ codejury install-slash-command --agent codex # Codex, ~/.codex/prompts/
37
+ ```
38
+
39
+ `install-slash-command` copies the `/codejury-review` command into the agent's
40
+ command directory. The command body is the same for every agent, only the
41
+ directory differs, so pass `--dir` for any other agent. The repo review itself is
42
+ agent neutral, so even without the command you can run `codejury review` and
43
+ tell any agent to follow the methodology it writes.
44
+
45
+ ## Diff Review
46
+
47
+ ```bash
48
+ # audit a diff file
49
+ codejury diff --diff-file changes.diff
50
+
51
+ # audit a git range in a repo
52
+ codejury diff --repo /path/to/app --git-range origin/main...HEAD
53
+
54
+ # from stdin
55
+ git diff HEAD~1 | codejury diff
56
+
57
+ # adversarial mode, more recall on subtle flaws, about 3x the cost
58
+ codejury diff --diff-file changes.diff --mode adversarial
59
+
60
+ # CI gate and SARIF
61
+ codejury diff --diff-file changes.diff --format sarif --fail-on high
62
+ ```
63
+
64
+ Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
65
+ the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
66
+ variables. `codejury diff --dry-run` exercises the engine with a mock
67
+ provider and no key, and falls back to a built in demo diff when you pass none.
68
+
69
+ ### Choosing a Model and Mode
70
+
71
+ Detection quality is dominated by the model first, then the mode. On real diff
72
+ probes:
73
+
74
+ - A strong model at the Claude Sonnet tier in standard mode caught every planted
75
+ vulnerability with almost no false positives. A weaker model raised false
76
+ positives in both modes, so the model is the lever that matters most.
77
+ - Adversarial mode did not lower false positives over standard on those probes
78
+ and costs about 3x. Reach for it to gain recall on subtle logic that spans
79
+ files, not as a way to cut false positives.
80
+
81
+ Default to standard mode with a strong model, set with `--model` or
82
+ `CODEJURY_MODEL`. False positives are held down by the do not report list and the
83
+ post filter, not by the mode.
84
+
85
+ ### Use in CI with GitHub Actions
86
+
87
+ Audit every pull request and surface findings in the code scanning tab. Copy
88
+ `examples/codejury-pr-review.yml` into `.github/workflows/`, add a
89
+ `CODEJURY_API_KEY` repository secret, and it will
90
+
91
+ 1. diff the pull request against its base with `--git-range origin/<base>...HEAD`,
92
+ 2. write SARIF and upload it with `github/codeql-action/upload-sarif`,
93
+ 3. fail the check on a HIGH or CRITICAL finding with `--fail-on high`.
94
+
95
+ The job makes one model call per pull request in standard mode. The SARIF is
96
+ uploaded even when the gate fails, so findings always show up on the pull
97
+ request.
98
+
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
+ ## Findings
146
+
147
+ Each finding carries a file and line, a severity and category, a concrete exploit
148
+ scenario, a recommendation, and a confidence. A false positive filter drops test
149
+ paths, mock paths, and low confidence noise. The model is also told not to report
150
+ dependency CVEs, style notes, speculation, or risks that only matter when
151
+ production config leaks.
152
+
153
+ ## Extending
154
+
155
+ Knowledge is data, so extending codejury is a drop-in markdown file with no code
156
+ change.
157
+
158
+ - A vulnerability class: `codejury/data/vulnerabilities/<class>.md` with
159
+ frontmatter of title, impact, tags, and triggers, plus a vulnerable and a
160
+ secure example.
161
+ - A language or framework: `codejury/data/languages/<lang>.md` or
162
+ `codejury/data/frameworks/<lang>/<framework>.md`, declaring its detect signals,
163
+ entrypoint markers, and downstream logic layers.
164
+ - A protocol such as OAuth: `codejury/data/protocols/<name>.md`, detected by
165
+ language neutral content tokens.
166
+ ```
@@ -0,0 +1,10 @@
1
+ """Entry point for `python -m codejury`, mirroring the `codejury` console script.
2
+
3
+ Lets the tool run without the console script on PATH, for example from a fresh
4
+ shell that has not activated the project venv: `python -m codejury ...`.
5
+ """
6
+
7
+ from codejury.cli import main
8
+
9
+ if __name__ == "__main__":
10
+ raise SystemExit(main())
@@ -2,13 +2,13 @@
2
2
 
3
3
  Two paths matched to their nature:
4
4
 
5
- - ``review diff`` runs the coded diff engine over a unified diff: a single
6
- balanced call (standard) or the adversarial Finder/Challenger/Judge pass.
7
- - ``review repo`` scaffolds a workspace and prints the methodology for an
5
+ - ``diff`` runs the coded diff engine over a unified diff: a single balanced call
6
+ (standard) or the adversarial Finder/Challenger/Judge pass.
7
+ - ``review <dir>`` scaffolds a workspace and prints the methodology for an
8
8
  interactive agent to run a whole-repo review (it does not run an LLM pipeline,
9
9
  which a single call cannot do for a whole codebase).
10
10
 
11
- ``review diff --dry-run`` exercises the engine with a mock provider and no key.
11
+ ``diff --dry-run`` exercises the engine with a mock provider and no key.
12
12
  The audit orchestration itself lives in ``codejury.diff.runner``.
13
13
  """
14
14
 
@@ -17,6 +17,7 @@ from __future__ import annotations
17
17
  import argparse
18
18
  import subprocess
19
19
  import sys
20
+ from pathlib import Path
20
21
 
21
22
  from codejury import __version__
22
23
  from codejury.report import gate, render
@@ -92,12 +93,17 @@ def main(argv: list[str] | None = None) -> int:
92
93
  parser.add_argument("--version", action="version", version=f"codejury {__version__}")
93
94
  sub = parser.add_subparsers(dest="command")
94
95
 
95
- review = sub.add_parser("review", help="review code for security findings")
96
- rsub = review.add_subparsers(dest="scope")
97
- _add_audit_args(rsub.add_parser("diff", help="audit a unified diff (the coded engine)"))
98
- repo = rsub.add_parser("repo", help="scaffold a whole-repo review for an interactive agent")
99
- repo.add_argument("directory", help="target repository to review")
100
- repo.add_argument("--workspace", default="codejury-review", help="where to create the review workspace")
96
+ _add_audit_args(sub.add_parser("diff", help="audit a unified diff (the coded engine)"))
97
+
98
+ review = sub.add_parser("review", help="scaffold a whole-repo review for an interactive agent")
99
+ review.add_argument("directory", help="target repository to review")
100
+ review.add_argument("--workspace", default="codejury-review", help="where to create the review workspace")
101
+
102
+ inst = sub.add_parser("install-slash-command",
103
+ help="install the /codejury-review slash command for an agent")
104
+ inst.add_argument("--agent", choices=("claude", "codex"), default="claude",
105
+ help="which agent's command directory to install into")
106
+ inst.add_argument("--dir", default=None, help="explicit target directory, overrides --agent")
101
107
 
102
108
  args = parser.parse_args(argv)
103
109
  try:
@@ -109,8 +115,7 @@ def main(argv: list[str] | None = None) -> int:
109
115
 
110
116
 
111
117
  def _dispatch(args, parser) -> int:
112
- scope = getattr(args, "scope", None)
113
- if args.command == "review" and scope == "diff":
118
+ if args.command == "diff":
114
119
  if args.dry_run:
115
120
  provider = MockProvider(default=_MOCK_REPLY)
116
121
  model = "mock"
@@ -129,23 +134,38 @@ def _dispatch(args, parser) -> int:
129
134
  print(render(args.fmt, kept))
130
135
  return 1 if gate(kept, args.fail_on) else 0
131
136
 
132
- if args.command == "review" and scope == "repo":
137
+ if args.command == "review":
133
138
  res = scaffold(args.directory, args.workspace)
134
- print(f"Workspace: {res.workspace}", file=sys.stderr)
139
+ (Path(res.workspace) / "METHODOLOGY.md").write_text(res.methodology, encoding="utf-8")
140
+ print(f"Workspace ready: {res.workspace}", file=sys.stderr)
135
141
  if res.guides:
136
- print(f"Detected stack: {', '.join(res.guides)}. Notes in {res.workspace}/_stack.md", file=sys.stderr)
142
+ print(f"Detected stack: {', '.join(res.guides)}, notes in {res.workspace}/_stack.md", file=sys.stderr)
137
143
  print(f"Flagged {len(res.candidate_files)} candidate entrypoint files into "
138
144
  f"{res.workspace}/entrypoints/_entrypoints.md", file=sys.stderr)
139
- print(f"Memory: {res.memory_path}", file=sys.stderr)
140
- print("\nRun this review with an interactive agent (Claude Code / Codex) using the methodology below.\n")
141
- print(res.methodology)
145
+ print(f"Methodology: {res.workspace}/METHODOLOGY.md", file=sys.stderr)
146
+ print(
147
+ "This command sets up the review, it does not find the issues itself. Next, have an "
148
+ 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 "
150
+ f"{res.workspace}/issues/."
151
+ )
142
152
  return 0
143
153
 
144
- if args.command == "review": # no scope given
145
- print("usage: codejury review {diff,repo} ...", file=sys.stderr)
146
- print(" diff audit a unified diff for security findings", file=sys.stderr)
147
- print(" repo scaffold a whole-repo review for an interactive agent", file=sys.stderr)
148
- return 1
154
+ if args.command == "install-slash-command":
155
+ from codejury.resources import COMMANDS_DIR
156
+ # the command body is portable, only the directory differs per agent
157
+ agent_dirs = {
158
+ "claude": Path.home() / ".claude" / "commands",
159
+ "codex": Path.home() / ".codex" / "prompts",
160
+ }
161
+ target_dir = Path(args.dir) if args.dir else agent_dirs[args.agent]
162
+ target_dir.mkdir(parents=True, exist_ok=True)
163
+ name = "codejury-review.md"
164
+ dst = target_dir / name
165
+ dst.write_text((COMMANDS_DIR / name).read_text(encoding="utf-8"), encoding="utf-8")
166
+ print(f"Installed slash command to {dst}")
167
+ print("Run it in the agent with: /codejury-review <repository>")
168
+ return 0
149
169
 
150
170
  parser.print_help()
151
171
  return 1
@@ -0,0 +1,29 @@
1
+ ---
2
+ description: Run a codejury whole-repo security review on a repository, interactively
3
+ ---
4
+ Run a codejury whole-repository security review of: $ARGUMENTS
5
+
6
+ 1. Scaffold the workspace:
7
+
8
+ ```
9
+ codejury review $ARGUMENTS --workspace /tmp/codejury-review
10
+ ```
11
+
12
+ If `codejury` is not on PATH it is a pip-installed console script, so activate
13
+ the project venv first, for example `. .venv/bin/activate`, or run it through
14
+ that venv's Python, for example `python -m codejury`.
15
+
16
+ 2. Read `<workspace>/METHODOLOGY.md` and follow it to completion. It is the single
17
+ source of truth for how to run the review, the entrypoint map, the trace
18
+ targets, the Authorization Model pass, the dependency-control checks, the round
19
+ ledger, and the Completeness Gate. Do not improvise a different process.
20
+
21
+ 3. Verify each issue with a real PoC, human in the loop. Ask me for any
22
+ credential, test account, or MFA step you need. Never touch production, never
23
+ use real credentials, and never run a destructive action without my go-ahead.
24
+ Only a reproduced PoC is a confirmed finding.
25
+
26
+ 4. Report confirmed findings, the ones with a reproduced PoC, separately from
27
+ suspected ones still blocked on verification, as a table: title, class,
28
+ `file:line`, exploit, verification status. The issue files live in the
29
+ workspace `issues/`.
@@ -4,7 +4,7 @@
4
4
  # data edit. This is distinct from a guide's stack detection, which decides which
5
5
  # language, framework, or protocol applies.
6
6
 
7
- skip_dirs: [".git", ".venv", "venv", "node_modules", "__pycache__", ".mypy_cache", ".pytest_cache"]
7
+ skip_dirs: [".git", ".venv", "venv", "node_modules", "__pycache__", ".mypy_cache", ".pytest_cache", "build", "dist", "target", "out", ".tox", ".eggs", ".next", ".nuxt"]
8
8
 
9
9
  source_extensions: [".py", ".js", ".ts", ".tsx", ".jsx", ".mjs", ".go", ".rb", ".java", ".kt", ".php", ".cs", ".scala", ".rs"]
10
10
 
@@ -147,10 +147,12 @@ exploitable exposure, so it is in scope. See "Controls That Live in a Library".
147
147
 
148
148
  ## Recording an Issue
149
149
 
150
- Write one `issues/<name>.md` per issue, and save its PoC as a real runnable file
151
- `issues/poc_<name>.<ext>`, a script or an `.http` file, not a sketch in prose. If
152
- you cannot write a concrete runnable PoC, the finding is most likely a false
153
- positive, so do not report it. Each issue file must have:
150
+ Write one `issues/<name>.md` per issue, the write-up only, and save its PoC as a
151
+ real runnable file `pocs/<name>.<ext>` with the **same `<name>`** so the two pair
152
+ one to one, a script or an `.http` file, not a sketch in prose and not a `.md`.
153
+ Keep `issues/` write-ups and `pocs/` scripts in their own directories, do not mix
154
+ them. If you cannot write a concrete runnable PoC, the finding is most likely a
155
+ false positive, so do not report it. Each issue file must have:
154
156
 
155
157
  ```markdown
156
158
  # <title>
@@ -167,7 +169,7 @@ positive, so do not report it. Each issue file must have:
167
169
  (end-to-end, actionable steps)
168
170
 
169
171
  ## PoC
170
- (the path to `issues/poc_<name>.<ext>` and how to run it)
172
+ (the path to `pocs/<name>.<ext>` and how to run it)
171
173
 
172
174
  ## Verification
173
175
  (the actual output of running the PoC, or the exact blocker)
@@ -151,7 +151,7 @@ def scaffold(target: str | Path, workspace: str | Path) -> ScaffoldResult:
151
151
  project = target.name
152
152
  ws = Path(workspace) / project
153
153
  created: list[str] = []
154
- for sub in ("entrypoints", "issues", "analysis"):
154
+ for sub in ("entrypoints", "issues", "pocs", "analysis"):
155
155
  d = ws / sub
156
156
  if not d.exists():
157
157
  d.mkdir(parents=True, exist_ok=True)
@@ -14,3 +14,4 @@ FRAMEWORKS_DIR = _DATA / "frameworks" # per-framework review guides (how the ta
14
14
  PROTOCOLS_DIR = _DATA / "protocols" # protocol guides such as oauth (what to check)
15
15
  METHODOLOGIES_DIR = _DATA / "methodologies" # repo-review methodology and memory template
16
16
  DETECTION_FILE = _DATA / "detection.yaml" # file and path classification across ecosystems
17
+ COMMANDS_DIR = _DATA / "commands" # Claude Code slash commands shipped for install