codejury 0.14.6__tar.gz → 0.15.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 (81) hide show
  1. {codejury-0.14.6 → codejury-0.15.0}/PKG-INFO +45 -14
  2. codejury-0.15.0/README.md +104 -0
  3. {codejury-0.14.6 → codejury-0.15.0}/codejury/cli.py +1 -1
  4. codejury-0.14.6/codejury/data/agent/full-review.md → codejury-0.15.0/codejury/data/agent/repo-review.md +13 -13
  5. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/SKILL.md +1 -1
  6. {codejury-0.14.6 → codejury-0.15.0}/codejury/repo/model.py +14 -6
  7. {codejury-0.14.6 → codejury-0.15.0}/codejury/repo/scaffold.py +8 -7
  8. {codejury-0.14.6 → codejury-0.15.0}/codejury/resources.py +1 -1
  9. {codejury-0.14.6 → codejury-0.15.0}/codejury.egg-info/PKG-INFO +45 -14
  10. {codejury-0.14.6 → codejury-0.15.0}/codejury.egg-info/SOURCES.txt +1 -1
  11. {codejury-0.14.6 → codejury-0.15.0}/pyproject.toml +1 -1
  12. {codejury-0.14.6 → codejury-0.15.0}/tests/test_repo_model.py +12 -6
  13. {codejury-0.14.6 → codejury-0.15.0}/tests/test_repo_scaffold.py +4 -4
  14. codejury-0.14.6/README.md +0 -73
  15. {codejury-0.14.6 → codejury-0.15.0}/LICENSE +0 -0
  16. {codejury-0.14.6 → codejury-0.15.0}/codejury/__init__.py +0 -0
  17. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/agent/security-review-memory.md +0 -0
  18. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/entrypoints.yaml +0 -0
  19. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/business-logic.md +0 -0
  20. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/code-injection.md +0 -0
  21. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/command-injection.md +0 -0
  22. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/cross-site-request-forgery.md +0 -0
  23. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/cross-site-scripting.md +0 -0
  24. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/hardcoded-secrets.md +0 -0
  25. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/http-response-splitting.md +0 -0
  26. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/improper-authentication.md +0 -0
  27. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/information-exposure.md +0 -0
  28. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/insecure-cryptography.md +0 -0
  29. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/insecure-deserialization.md +0 -0
  30. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/insecure-direct-object-reference.md +0 -0
  31. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/insecure-transport.md +0 -0
  32. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/jwt-validation.md +0 -0
  33. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/mass-assignment.md +0 -0
  34. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/missing-authorization.md +0 -0
  35. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/open-redirect.md +0 -0
  36. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/path-traversal.md +0 -0
  37. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/race-condition.md +0 -0
  38. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/replay-attack.md +0 -0
  39. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/server-side-request-forgery.md +0 -0
  40. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/server-side-template-injection.md +0 -0
  41. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/session-fixation.md +0 -0
  42. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/sql-injection.md +0 -0
  43. {codejury-0.14.6 → codejury-0.15.0}/codejury/data/rules/xml-external-entity.md +0 -0
  44. {codejury-0.14.6 → codejury-0.15.0}/codejury/diff/__init__.py +0 -0
  45. {codejury-0.14.6 → codejury-0.15.0}/codejury/diff/debate.py +0 -0
  46. {codejury-0.14.6 → codejury-0.15.0}/codejury/diff/debate_prompts.py +0 -0
  47. {codejury-0.14.6 → codejury-0.15.0}/codejury/diff/engine.py +0 -0
  48. {codejury-0.14.6 → codejury-0.15.0}/codejury/diff/findings_filter.py +0 -0
  49. {codejury-0.14.6 → codejury-0.15.0}/codejury/diff/prompts.py +0 -0
  50. {codejury-0.14.6 → codejury-0.15.0}/codejury/diff/rules.py +0 -0
  51. {codejury-0.14.6 → codejury-0.15.0}/codejury/diff/runner.py +0 -0
  52. {codejury-0.14.6 → codejury-0.15.0}/codejury/domain/__init__.py +0 -0
  53. {codejury-0.14.6 → codejury-0.15.0}/codejury/domain/finding.py +0 -0
  54. {codejury-0.14.6 → codejury-0.15.0}/codejury/json_parse.py +0 -0
  55. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/__init__.py +0 -0
  56. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/anthropic.py +0 -0
  57. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/base.py +0 -0
  58. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/factory.py +0 -0
  59. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/litellm.py +0 -0
  60. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/mock.py +0 -0
  61. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/openai.py +0 -0
  62. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/openai_format.py +0 -0
  63. {codejury-0.14.6 → codejury-0.15.0}/codejury/providers/retry.py +0 -0
  64. {codejury-0.14.6 → codejury-0.15.0}/codejury/repo/__init__.py +0 -0
  65. {codejury-0.14.6 → codejury-0.15.0}/codejury/report.py +0 -0
  66. {codejury-0.14.6 → codejury-0.15.0}/codejury.egg-info/dependency_links.txt +0 -0
  67. {codejury-0.14.6 → codejury-0.15.0}/codejury.egg-info/entry_points.txt +0 -0
  68. {codejury-0.14.6 → codejury-0.15.0}/codejury.egg-info/requires.txt +0 -0
  69. {codejury-0.14.6 → codejury-0.15.0}/codejury.egg-info/top_level.txt +0 -0
  70. {codejury-0.14.6 → codejury-0.15.0}/setup.cfg +0 -0
  71. {codejury-0.14.6 → codejury-0.15.0}/tests/test_anthropic_provider.py +0 -0
  72. {codejury-0.14.6 → codejury-0.15.0}/tests/test_cli_audit.py +0 -0
  73. {codejury-0.14.6 → codejury-0.15.0}/tests/test_diff_debate.py +0 -0
  74. {codejury-0.14.6 → codejury-0.15.0}/tests/test_diff_engine.py +0 -0
  75. {codejury-0.14.6 → codejury-0.15.0}/tests/test_json_parse.py +0 -0
  76. {codejury-0.14.6 → codejury-0.15.0}/tests/test_litellm_provider.py +0 -0
  77. {codejury-0.14.6 → codejury-0.15.0}/tests/test_openai_format.py +0 -0
  78. {codejury-0.14.6 → codejury-0.15.0}/tests/test_openai_provider.py +0 -0
  79. {codejury-0.14.6 → codejury-0.15.0}/tests/test_report.py +0 -0
  80. {codejury-0.14.6 → codejury-0.15.0}/tests/test_retry_provider.py +0 -0
  81. {codejury-0.14.6 → codejury-0.15.0}/tests/test_rules.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codejury
3
- Version: 0.14.6
3
+ Version: 0.15.0
4
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
5
  Author: AISecLabs
6
6
  License-Expression: MIT
@@ -34,13 +34,14 @@ Dynamic: license-file
34
34
  AI code security review, in two paths matched to their nature:
35
35
 
36
36
  - **Diff review** (coded): audit a pull request's diff for newly introduced,
37
- exploitable risks. A single balanced LLM call, or an adversarial
38
- Finder/Challenger/Judge pass for higher coverage and fewer false positives.
37
+ exploitable risks. A single balanced LLM call (the default), or an adversarial
38
+ Finder/Challenger/Judge pass that trades roughly 3x the cost for extra recall
39
+ on subtle, cross-cutting flaws.
39
40
  - **Whole-repo review** (agent-driven): a methodology an interactive agent
40
- (Claude Code, Codex) runs to traverse a codebase from its API entrypoints,
41
- verify issues with a real PoC, and iterate over rounds with a persistent
42
- memory. Too large for a single LLM call, so codejury ships the methodology and
43
- scaffolds the workspace rather than running a pipeline.
41
+ (Claude Code, Codex) runs to map a codebase's attack surface, trace inputs to
42
+ sinks across files, verify issues with a real PoC, and iterate over rounds with
43
+ a persistent memory. Too large for a single LLM call, so codejury ships the
44
+ methodology and scaffolds the workspace rather than running a pipeline.
44
45
 
45
46
  Security knowledge lives in **rich rules** (`codejury/data/rules/*.md`, with
46
47
  per-language vulnerable/secure examples), injected into the audit prompt, not
@@ -65,7 +66,7 @@ codejury review diff --repo /path/to/app --git-range origin/main...HEAD
65
66
  # from stdin
66
67
  git diff HEAD~1 | codejury review diff
67
68
 
68
- # adversarial mode: Finder + Challenger + Judge (higher coverage, lower FP, ~3x cost)
69
+ # adversarial mode: Finder + Challenger + Judge (extra recall on subtle flaws, ~3x cost)
69
70
  codejury review diff --diff-file changes.diff --mode adversarial
70
71
 
71
72
  # CI gate + SARIF
@@ -77,18 +78,48 @@ Configure a backend with `--provider`/`--model`/`--api-key`/`--api-base` or the
77
78
  `codejury review diff --dry-run` exercises the engine with a mock provider and
78
79
  no key (it uses a built-in demo diff when you do not pass one).
79
80
 
81
+ ### Choosing a model and mode
82
+
83
+ Detection quality is dominated by the model first, then the mode. On real-diff
84
+ probes:
85
+
86
+ - A strong model (Claude Sonnet tier) in **standard** mode caught every planted
87
+ vulnerability with near-zero false positives. A weaker model raised false
88
+ positives in both modes, so the model is the lever that matters most.
89
+ - **Adversarial** mode did not lower false positives over standard on those
90
+ probes and costs ~3x. Reach for it for extra recall on subtle, cross-file
91
+ logic, not as a false-positive reducer.
92
+
93
+ Default to **standard mode with a strong model** (set it with `--model` or
94
+ `CODEJURY_MODEL`). False positives are held down by the do-not-report list and
95
+ the post-filter, not by the mode.
96
+
97
+ ### Use in CI (GitHub Actions)
98
+
99
+ Audit every pull request and surface findings in the code scanning tab. Copy
100
+ [`examples/codejury-pr-review.yml`](examples/codejury-pr-review.yml) into
101
+ `.github/workflows/`, add a `CODEJURY_API_KEY` repo secret, and it will:
102
+
103
+ 1. diff the PR against its base (`--git-range origin/<base>...HEAD`),
104
+ 2. write SARIF and upload it with `github/codeql-action/upload-sarif`,
105
+ 3. fail the check on a HIGH or CRITICAL finding (`--fail-on high`).
106
+
107
+ The job makes one model call per PR (standard mode); the SARIF is uploaded even
108
+ when the gate fails, so findings always show up on the PR.
109
+
80
110
  ## Whole-repo review
81
111
 
82
112
  ```bash
83
113
  codejury review repo /path/to/your/repo
84
114
  ```
85
115
 
86
- This scaffolds a review workspace (`api/`, `issues/`, `analysis/`, and a
87
- `security-review-memory.md`), seeds the API inventory from a deterministic scan,
88
- and prints the methodology. Run it with an interactive agent: it reads the
89
- methodology and the rules, traverses the code from its API entrypoints, records
90
- high-confidence issues with a PoC, and asks you to confirm credentials or false
91
- positives along the way. Nothing runs against production.
116
+ This scaffolds a review workspace (`entrypoints/`, `issues/`, `analysis/`, and a
117
+ `security-review-memory.md`), seeds the entrypoint inventory from a
118
+ deterministic scan, and prints the methodology. Run it with an interactive
119
+ agent: it reads the methodology and the rules, maps the attack surface, traces
120
+ inputs to sinks across files, records high-confidence issues with a PoC, and
121
+ asks you to confirm credentials or false positives along the way. Nothing runs
122
+ against production.
92
123
 
93
124
  ## Findings
94
125
 
@@ -0,0 +1,104 @@
1
+ # codejury
2
+
3
+ AI code security review, in two paths matched to their nature:
4
+
5
+ - **Diff review** (coded): audit a pull request's diff for newly introduced,
6
+ exploitable risks. A single balanced LLM call (the default), or an adversarial
7
+ Finder/Challenger/Judge pass that trades roughly 3x the cost for extra recall
8
+ on subtle, cross-cutting flaws.
9
+ - **Whole-repo review** (agent-driven): a methodology an interactive agent
10
+ (Claude Code, Codex) runs to map a codebase's attack surface, trace inputs to
11
+ sinks across files, verify issues with a real PoC, and iterate over rounds with
12
+ a persistent memory. Too large for a single LLM call, so codejury ships the
13
+ methodology and scaffolds the workspace rather than running a pipeline.
14
+
15
+ Security knowledge lives in **rich rules** (`codejury/data/rules/*.md`, with
16
+ per-language vulnerable/secure examples), injected into the audit prompt, not
17
+ buried in code.
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ pip install codejury # core
23
+ pip install "codejury[anthropic]" # or [openai] / [litellm] for a backend
24
+ ```
25
+
26
+ ## Diff review
27
+
28
+ ```bash
29
+ # audit a diff file
30
+ codejury review diff --diff-file changes.diff
31
+
32
+ # audit a git range in a repo
33
+ codejury review diff --repo /path/to/app --git-range origin/main...HEAD
34
+
35
+ # from stdin
36
+ git diff HEAD~1 | codejury review diff
37
+
38
+ # adversarial mode: Finder + Challenger + Judge (extra recall on subtle flaws, ~3x cost)
39
+ codejury review diff --diff-file changes.diff --mode adversarial
40
+
41
+ # CI gate + SARIF
42
+ codejury review diff --diff-file changes.diff --format sarif --fail-on high
43
+ ```
44
+
45
+ Configure a backend with `--provider`/`--model`/`--api-key`/`--api-base` or the
46
+ `CODEJURY_API_KEY` / `CODEJURY_MODEL` / `CODEJURY_API_BASE` environment variables.
47
+ `codejury review diff --dry-run` exercises the engine with a mock provider and
48
+ no key (it uses a built-in demo diff when you do not pass one).
49
+
50
+ ### Choosing a model and mode
51
+
52
+ Detection quality is dominated by the model first, then the mode. On real-diff
53
+ probes:
54
+
55
+ - A strong model (Claude Sonnet tier) in **standard** mode caught every planted
56
+ vulnerability with near-zero false positives. A weaker model raised false
57
+ positives in both modes, so the model is the lever that matters most.
58
+ - **Adversarial** mode did not lower false positives over standard on those
59
+ probes and costs ~3x. Reach for it for extra recall on subtle, cross-file
60
+ logic, not as a false-positive reducer.
61
+
62
+ Default to **standard mode with a strong model** (set it with `--model` or
63
+ `CODEJURY_MODEL`). False positives are held down by the do-not-report list and
64
+ the post-filter, not by the mode.
65
+
66
+ ### Use in CI (GitHub Actions)
67
+
68
+ Audit every pull request and surface findings in the code scanning tab. Copy
69
+ [`examples/codejury-pr-review.yml`](examples/codejury-pr-review.yml) into
70
+ `.github/workflows/`, add a `CODEJURY_API_KEY` repo secret, and it will:
71
+
72
+ 1. diff the PR against its base (`--git-range origin/<base>...HEAD`),
73
+ 2. write SARIF and upload it with `github/codeql-action/upload-sarif`,
74
+ 3. fail the check on a HIGH or CRITICAL finding (`--fail-on high`).
75
+
76
+ The job makes one model call per PR (standard mode); the SARIF is uploaded even
77
+ when the gate fails, so findings always show up on the PR.
78
+
79
+ ## Whole-repo review
80
+
81
+ ```bash
82
+ codejury review repo /path/to/your/repo
83
+ ```
84
+
85
+ This scaffolds a review workspace (`entrypoints/`, `issues/`, `analysis/`, and a
86
+ `security-review-memory.md`), seeds the entrypoint inventory from a
87
+ deterministic scan, and prints the methodology. Run it with an interactive
88
+ agent: it reads the methodology and the rules, maps the attack surface, traces
89
+ inputs to sinks across files, records high-confidence issues with a PoC, and
90
+ asks you to confirm credentials or false positives along the way. Nothing runs
91
+ against production.
92
+
93
+ ## Findings
94
+
95
+ Each finding carries a file and line, a severity and category, a concrete
96
+ exploit scenario, a recommendation, and a confidence. A false-positive filter
97
+ drops test/mock-path and low-confidence noise; the model is also told not to
98
+ report dependency CVEs, style notes, speculation, or config-leak-only risks.
99
+
100
+ ## Extending
101
+
102
+ Add a vulnerability class by dropping a new `codejury/data/rules/<class>.md` with
103
+ the standard frontmatter (title, impact, tags, triggers) and vulnerable/secure
104
+ examples. It is data; no code change needed.
@@ -132,7 +132,7 @@ def _dispatch(args, parser) -> int:
132
132
  if args.command == "review" and scope == "repo":
133
133
  res = scaffold(args.directory, args.workspace)
134
134
  print(f"Workspace: {res.workspace}", file=sys.stderr)
135
- print(f"Seeded {res.entrypoints} entrypoints into {res.workspace}/api/_entrypoints.md", file=sys.stderr)
135
+ print(f"Seeded {res.entrypoints} entrypoints into {res.workspace}/entrypoints/_entrypoints.md", file=sys.stderr)
136
136
  print(f"Memory: {res.memory_path}", file=sys.stderr)
137
137
  print("\nRun this review with an interactive agent (Claude Code / Codex) using the methodology below.\n")
138
138
  print(res.methodology)
@@ -1,13 +1,13 @@
1
- # Full Security Review — Agent Methodology
1
+ # Repo Security Review — Agent Methodology
2
2
 
3
- A whole-repository security audit, run by an interactive coding agent (Claude
4
- Code, Codex, etc.), not a one-shot LLM call. It maps the attack surface, traces
5
- inputs to sinks across files, verifies issues with a real PoC, and
6
- iterates over multiple rounds with a persistent memory. One round is roughly
7
- 30 minutes; run as many rounds as needed.
3
+ The `review repo` path: a whole-repository security audit, run by an interactive
4
+ coding agent (Claude Code, Codex, etc.), not a one-shot LLM call. It maps the
5
+ attack surface, traces inputs to sinks across files, verifies issues with a real
6
+ PoC, and iterates over multiple rounds with a persistent memory. One round is
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>/` (created for you), holding `api/`,
10
+ Workspace: `<workspace>/<project>/` (created for you), holding `entrypoints/`,
11
11
  `issues/`, `analysis/`, and `security-review-memory.md`.
12
12
 
13
13
  ---
@@ -18,9 +18,9 @@ Workspace: `<workspace>/<project>/` (created for you), holding `api/`,
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 `api/_entrypoints.md` (seeded for you from a deterministic AST scan) as a
22
- *starting* map of the attack surface. It lists HTTP routes and CLI commands
23
- only, so it is a subset, not the whole surface (see "Map the attack surface").
21
+ 2. Read `entrypoints/_entrypoints.md` (seeded for you from a deterministic AST
22
+ scan) as a *starting* map of the attack surface. It lists HTTP routes and CLI
23
+ commands only, a subset, not the whole surface (see "Map the attack surface").
24
24
  3. Read the relevant rule files under the shipped `rules/` for the target's stack
25
25
  (sql-injection, idor, ssrf, authentication-jwt, insecure-deserialization, ...).
26
26
 
@@ -28,7 +28,7 @@ Workspace: `<workspace>/<project>/` (created for you), holding `api/`,
28
28
 
29
29
  The seeded inventory lists HTTP routes and CLI commands only. Before analysing,
30
30
  complete the surface: untrusted input enters at more than HTTP. Enumerate every
31
- source the attacker can influence and add it to `api/`:
31
+ source the attacker can influence and add it to `entrypoints/`:
32
32
 
33
33
  - HTTP routes, GraphQL resolvers, gRPC / RPC handlers, WebSocket handlers;
34
34
  - CLI commands, scheduled jobs / cron, queue and topic consumers, webhooks and
@@ -40,8 +40,8 @@ source the attacker can influence and add it to `api/`:
40
40
  inter-service calls.
41
41
 
42
42
  `pickle.loads(cookie)` and `yaml.load(upload)` are entrypoints just as much as a
43
- route is. Record the inventory in `api/` (one file per module: source + auth
44
- method + review status ✅/⚠️/❌).
43
+ route is. Record the inventory in `entrypoints/` (one file per module: source +
44
+ auth method + review status ✅/⚠️/❌).
45
45
 
46
46
  ## Analyse each source
47
47
 
@@ -8,7 +8,7 @@ description: "Application security rules for reviewing code for exploitable vuln
8
8
  Application-security rules, one file per weakness class under `rules/`, named by
9
9
  the specific weakness (CWE-style). Each rule states impact, the markers to hunt
10
10
  (`triggers`), and vulnerable-vs-secure examples. The diff-audit engine injects the
11
- rules relevant to a change into the prompt; the full-review agent reads them for
11
+ rules relevant to a change into the prompt; the repo-review agent reads them for
12
12
  the target's stack. A finding's `category` is one of these ids.
13
13
 
14
14
  ## Rules by OWASP category
@@ -245,10 +245,18 @@ def _method(decorator_name: str, call: ast.Call | None, rule: str) -> str:
245
245
 
246
246
  def _view_name(call: ast.Call) -> str:
247
247
  # Django path("route", view): the view is the second positional argument
248
- if len(call.args) >= 2:
249
- view = call.args[1]
250
- if isinstance(view, ast.Name):
251
- return view.id
252
- if isinstance(view, ast.Attribute):
253
- return view.attr
248
+ if len(call.args) < 2:
249
+ return ""
250
+ view = call.args[1]
251
+ if isinstance(view, ast.Name):
252
+ return view.id
253
+ if isinstance(view, ast.Attribute):
254
+ return view.attr
255
+ # class-based view: SomeView.as_view() / views.SomeView.as_view() -> class name
256
+ if isinstance(view, ast.Call) and isinstance(view.func, ast.Attribute) and view.func.attr == "as_view":
257
+ target = view.func.value
258
+ if isinstance(target, ast.Name):
259
+ return target.id
260
+ if isinstance(target, ast.Attribute):
261
+ return target.attr
254
262
  return ""
@@ -3,9 +3,9 @@
3
3
  The `review repo` path. Whole-repo review is too large for a single LLM call, so
4
4
  codejury does not run it as a pipeline. Instead it scaffolds a workspace for an
5
5
  interactive agent (Claude Code, Codex) and hands over the methodology: it creates
6
- the api/issues/analysis directories, copies the review-memory template, seeds the
7
- API inventory from a deterministic RepoModel scan, and returns the methodology
8
- text to print.
6
+ the entrypoints/issues/analysis directories, copies the review-memory template,
7
+ seeds the entrypoint inventory from a deterministic RepoModel scan, and returns
8
+ the methodology text to print.
9
9
  """
10
10
 
11
11
  from __future__ import annotations
@@ -16,7 +16,7 @@ from pathlib import Path
16
16
  from codejury.repo.model import build_repo_model_from_dir
17
17
  from codejury.resources import AGENT_DIR
18
18
 
19
- _METHODOLOGY = AGENT_DIR / "full-review.md"
19
+ _METHODOLOGY = AGENT_DIR / "repo-review.md"
20
20
  _MEMORY_TEMPLATE = AGENT_DIR / "security-review-memory.md"
21
21
 
22
22
 
@@ -33,7 +33,8 @@ class ScaffoldResult:
33
33
  def _entrypoints_md(model) -> str:
34
34
  http = [e for e in model.entrypoints if e.kind == "http"]
35
35
  cli = [e for e in model.entrypoints if e.kind == "cli"]
36
- lines = ["# API Entrypoints (seeded from a deterministic scan)", "",
36
+ lines = ["# Entrypoints (seeded from a deterministic scan)", "",
37
+ "HTTP routes and CLI commands only; add non-HTTP sources here too.", "",
37
38
  "Status legend: ❌ not reviewed · ⚠️ to deepen · ✅ reviewed", ""]
38
39
  if http:
39
40
  lines += ["## HTTP routes", ""]
@@ -53,7 +54,7 @@ def scaffold(target: str | Path, workspace: str | Path) -> ScaffoldResult:
53
54
  project = target.name
54
55
  ws = Path(workspace) / project
55
56
  created: list[str] = []
56
- for sub in ("api", "issues", "analysis"):
57
+ for sub in ("entrypoints", "issues", "analysis"):
57
58
  d = ws / sub
58
59
  if not d.exists():
59
60
  d.mkdir(parents=True, exist_ok=True)
@@ -66,7 +67,7 @@ def scaffold(target: str | Path, workspace: str | Path) -> ScaffoldResult:
66
67
  created.append(str(memory_path))
67
68
 
68
69
  model = build_repo_model_from_dir(target)
69
- (ws / "api" / "_entrypoints.md").write_text(_entrypoints_md(model), encoding="utf-8")
70
+ (ws / "entrypoints" / "_entrypoints.md").write_text(_entrypoints_md(model), encoding="utf-8")
70
71
 
71
72
  return ScaffoldResult(
72
73
  project=project,
@@ -9,5 +9,5 @@ from pathlib import Path
9
9
  _DATA = Path(__file__).resolve().parent / "data"
10
10
 
11
11
  RULES_DIR = _DATA / "rules" # security rules injected into the audit prompt
12
- AGENT_DIR = _DATA / "agent" # full-review methodology and memory template
12
+ AGENT_DIR = _DATA / "agent" # repo-review methodology and memory template
13
13
  ENTRYPOINTS_FILE = _DATA / "entrypoints.yaml" # framework signatures for RepoModel
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codejury
3
- Version: 0.14.6
3
+ Version: 0.15.0
4
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
5
  Author: AISecLabs
6
6
  License-Expression: MIT
@@ -34,13 +34,14 @@ Dynamic: license-file
34
34
  AI code security review, in two paths matched to their nature:
35
35
 
36
36
  - **Diff review** (coded): audit a pull request's diff for newly introduced,
37
- exploitable risks. A single balanced LLM call, or an adversarial
38
- Finder/Challenger/Judge pass for higher coverage and fewer false positives.
37
+ exploitable risks. A single balanced LLM call (the default), or an adversarial
38
+ Finder/Challenger/Judge pass that trades roughly 3x the cost for extra recall
39
+ on subtle, cross-cutting flaws.
39
40
  - **Whole-repo review** (agent-driven): a methodology an interactive agent
40
- (Claude Code, Codex) runs to traverse a codebase from its API entrypoints,
41
- verify issues with a real PoC, and iterate over rounds with a persistent
42
- memory. Too large for a single LLM call, so codejury ships the methodology and
43
- scaffolds the workspace rather than running a pipeline.
41
+ (Claude Code, Codex) runs to map a codebase's attack surface, trace inputs to
42
+ sinks across files, verify issues with a real PoC, and iterate over rounds with
43
+ a persistent memory. Too large for a single LLM call, so codejury ships the
44
+ methodology and scaffolds the workspace rather than running a pipeline.
44
45
 
45
46
  Security knowledge lives in **rich rules** (`codejury/data/rules/*.md`, with
46
47
  per-language vulnerable/secure examples), injected into the audit prompt, not
@@ -65,7 +66,7 @@ codejury review diff --repo /path/to/app --git-range origin/main...HEAD
65
66
  # from stdin
66
67
  git diff HEAD~1 | codejury review diff
67
68
 
68
- # adversarial mode: Finder + Challenger + Judge (higher coverage, lower FP, ~3x cost)
69
+ # adversarial mode: Finder + Challenger + Judge (extra recall on subtle flaws, ~3x cost)
69
70
  codejury review diff --diff-file changes.diff --mode adversarial
70
71
 
71
72
  # CI gate + SARIF
@@ -77,18 +78,48 @@ Configure a backend with `--provider`/`--model`/`--api-key`/`--api-base` or the
77
78
  `codejury review diff --dry-run` exercises the engine with a mock provider and
78
79
  no key (it uses a built-in demo diff when you do not pass one).
79
80
 
81
+ ### Choosing a model and mode
82
+
83
+ Detection quality is dominated by the model first, then the mode. On real-diff
84
+ probes:
85
+
86
+ - A strong model (Claude Sonnet tier) in **standard** mode caught every planted
87
+ vulnerability with near-zero false positives. A weaker model raised false
88
+ positives in both modes, so the model is the lever that matters most.
89
+ - **Adversarial** mode did not lower false positives over standard on those
90
+ probes and costs ~3x. Reach for it for extra recall on subtle, cross-file
91
+ logic, not as a false-positive reducer.
92
+
93
+ Default to **standard mode with a strong model** (set it with `--model` or
94
+ `CODEJURY_MODEL`). False positives are held down by the do-not-report list and
95
+ the post-filter, not by the mode.
96
+
97
+ ### Use in CI (GitHub Actions)
98
+
99
+ Audit every pull request and surface findings in the code scanning tab. Copy
100
+ [`examples/codejury-pr-review.yml`](examples/codejury-pr-review.yml) into
101
+ `.github/workflows/`, add a `CODEJURY_API_KEY` repo secret, and it will:
102
+
103
+ 1. diff the PR against its base (`--git-range origin/<base>...HEAD`),
104
+ 2. write SARIF and upload it with `github/codeql-action/upload-sarif`,
105
+ 3. fail the check on a HIGH or CRITICAL finding (`--fail-on high`).
106
+
107
+ The job makes one model call per PR (standard mode); the SARIF is uploaded even
108
+ when the gate fails, so findings always show up on the PR.
109
+
80
110
  ## Whole-repo review
81
111
 
82
112
  ```bash
83
113
  codejury review repo /path/to/your/repo
84
114
  ```
85
115
 
86
- This scaffolds a review workspace (`api/`, `issues/`, `analysis/`, and a
87
- `security-review-memory.md`), seeds the API inventory from a deterministic scan,
88
- and prints the methodology. Run it with an interactive agent: it reads the
89
- methodology and the rules, traverses the code from its API entrypoints, records
90
- high-confidence issues with a PoC, and asks you to confirm credentials or false
91
- positives along the way. Nothing runs against production.
116
+ This scaffolds a review workspace (`entrypoints/`, `issues/`, `analysis/`, and a
117
+ `security-review-memory.md`), seeds the entrypoint inventory from a
118
+ deterministic scan, and prints the methodology. Run it with an interactive
119
+ agent: it reads the methodology and the rules, maps the attack surface, traces
120
+ inputs to sinks across files, records high-confidence issues with a PoC, and
121
+ asks you to confirm credentials or false positives along the way. Nothing runs
122
+ against production.
92
123
 
93
124
  ## Findings
94
125
 
@@ -13,7 +13,7 @@ codejury.egg-info/entry_points.txt
13
13
  codejury.egg-info/requires.txt
14
14
  codejury.egg-info/top_level.txt
15
15
  codejury/data/entrypoints.yaml
16
- codejury/data/agent/full-review.md
16
+ codejury/data/agent/repo-review.md
17
17
  codejury/data/agent/security-review-memory.md
18
18
  codejury/data/rules/SKILL.md
19
19
  codejury/data/rules/business-logic.md
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codejury"
3
- version = "0.14.6"
3
+ version = "0.15.0"
4
4
  description = "AI code security review: an adversarial diff-audit engine and an agent-driven whole-repo review methodology, with security knowledge as rich rules"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -59,7 +59,8 @@ urlpatterns = [
59
59
  ]
60
60
  '''
61
61
 
62
- # include() mounts and class-based views resolve to no handler function: noise
62
+ # include() to a module not in the tree resolves to no file: dropped.
63
+ # class-based views resolve to the view class name.
63
64
  DJANGO_NOISE = '''
64
65
  from django.urls import path, include
65
66
  from .views import DashboardView
@@ -69,6 +70,7 @@ urlpatterns = [
69
70
  path("accounts/", include("allauth.urls")),
70
71
  path("profile/", views.profile),
71
72
  path("dash/", DashboardView.as_view()),
73
+ path("admin-panel/", views.AdminView.as_view()),
72
74
  ]
73
75
  '''
74
76
 
@@ -163,12 +165,16 @@ def test_django_include_mounts_subroutes_under_prefix():
163
165
  assert all(e.route != "users" for e in model.entrypoints)
164
166
 
165
167
 
166
- def test_django_include_and_cbv_with_no_resolvable_function_are_dropped():
167
- # include() mounts and an unresolved .as_view() carry no handler function;
168
- # only the plain function-based view survives, no empty `- -` noise entries
168
+ def test_django_unresolvable_include_dropped_and_cbv_resolved():
169
+ # include() whose module is not in the tree resolves to no file and is dropped;
170
+ # class-based views resolve to the view class name (both Name and views.Attr forms)
169
171
  model = _model({"urls.py": DJANGO_NOISE})
170
- assert _routes(model) == {("http", "django", "profile", "profile/", "")}
171
- assert all(e.function for e in model.entrypoints)
172
+ assert _routes(model) == {
173
+ ("http", "django", "profile", "profile/", ""),
174
+ ("http", "django", "DashboardView", "dash/", ""),
175
+ ("http", "django", "AdminView", "admin-panel/", ""),
176
+ }
177
+ assert all(e.function for e in model.entrypoints) # no empty `- -` noise entries
172
178
 
173
179
 
174
180
  def test_plain_module_has_no_entrypoints():
@@ -1,4 +1,4 @@
1
- """RW-4: the full-review scaffold sets up the agent workspace (api/issues/
1
+ """RW-4: the repo-review scaffold sets up the agent workspace (entrypoints/issues/
2
2
  analysis + memory + seeded entrypoints) and returns the methodology. It does not
3
3
  run an LLM pipeline."""
4
4
 
@@ -32,7 +32,7 @@ def test_scaffold_creates_workspace(tmp_path):
32
32
 
33
33
  assert res.project == "myservice"
34
34
  assert res.workspace == ws_root / "myservice"
35
- for sub in ("api", "issues", "analysis"):
35
+ for sub in ("entrypoints", "issues", "analysis"):
36
36
  assert (res.workspace / sub).is_dir()
37
37
  assert res.memory_path.is_file()
38
38
  assert "Security Review Memory" in res.memory_path.read_text()
@@ -42,7 +42,7 @@ def test_scaffold_creates_workspace(tmp_path):
42
42
  def test_scaffold_seeds_entrypoints_from_repomodel(tmp_path):
43
43
  res = scaffold(_target(tmp_path), tmp_path / "work")
44
44
  assert res.entrypoints == 2
45
- seeded = (res.workspace / "api" / "_entrypoints.md").read_text()
45
+ seeded = (res.workspace / "entrypoints" / "_entrypoints.md").read_text()
46
46
  assert "/users" in seeded and "/admin/users/<uid>" in seeded
47
47
  assert "list_users" in seeded and "❌" in seeded
48
48
 
@@ -71,4 +71,4 @@ def test_no_python_entrypoints_still_scaffolds(tmp_path):
71
71
  (d / "notes.txt").write_text("hi")
72
72
  res = scaffold(d, tmp_path / "work")
73
73
  assert res.entrypoints == 0
74
- assert "enumerate them manually" in (res.workspace / "api" / "_entrypoints.md").read_text()
74
+ assert "enumerate them manually" in (res.workspace / "entrypoints" / "_entrypoints.md").read_text()
codejury-0.14.6/README.md DELETED
@@ -1,73 +0,0 @@
1
- # codejury
2
-
3
- AI code security review, in two paths matched to their nature:
4
-
5
- - **Diff review** (coded): audit a pull request's diff for newly introduced,
6
- exploitable risks. A single balanced LLM call, or an adversarial
7
- Finder/Challenger/Judge pass for higher coverage and fewer false positives.
8
- - **Whole-repo review** (agent-driven): a methodology an interactive agent
9
- (Claude Code, Codex) runs to traverse a codebase from its API entrypoints,
10
- verify issues with a real PoC, and iterate over rounds with a persistent
11
- memory. Too large for a single LLM call, so codejury ships the methodology and
12
- scaffolds the workspace rather than running a pipeline.
13
-
14
- Security knowledge lives in **rich rules** (`codejury/data/rules/*.md`, with
15
- per-language vulnerable/secure examples), injected into the audit prompt, not
16
- buried in code.
17
-
18
- ## Install
19
-
20
- ```bash
21
- pip install codejury # core
22
- pip install "codejury[anthropic]" # or [openai] / [litellm] for a backend
23
- ```
24
-
25
- ## Diff review
26
-
27
- ```bash
28
- # audit a diff file
29
- codejury review diff --diff-file changes.diff
30
-
31
- # audit a git range in a repo
32
- codejury review diff --repo /path/to/app --git-range origin/main...HEAD
33
-
34
- # from stdin
35
- git diff HEAD~1 | codejury review diff
36
-
37
- # adversarial mode: Finder + Challenger + Judge (higher coverage, lower FP, ~3x cost)
38
- codejury review diff --diff-file changes.diff --mode adversarial
39
-
40
- # CI gate + SARIF
41
- codejury review diff --diff-file changes.diff --format sarif --fail-on high
42
- ```
43
-
44
- Configure a backend with `--provider`/`--model`/`--api-key`/`--api-base` or the
45
- `CODEJURY_API_KEY` / `CODEJURY_MODEL` / `CODEJURY_API_BASE` environment variables.
46
- `codejury review diff --dry-run` exercises the engine with a mock provider and
47
- no key (it uses a built-in demo diff when you do not pass one).
48
-
49
- ## Whole-repo review
50
-
51
- ```bash
52
- codejury review repo /path/to/your/repo
53
- ```
54
-
55
- This scaffolds a review workspace (`api/`, `issues/`, `analysis/`, and a
56
- `security-review-memory.md`), seeds the API inventory from a deterministic scan,
57
- and prints the methodology. Run it with an interactive agent: it reads the
58
- methodology and the rules, traverses the code from its API entrypoints, records
59
- high-confidence issues with a PoC, and asks you to confirm credentials or false
60
- positives along the way. Nothing runs against production.
61
-
62
- ## Findings
63
-
64
- Each finding carries a file and line, a severity and category, a concrete
65
- exploit scenario, a recommendation, and a confidence. A false-positive filter
66
- drops test/mock-path and low-confidence noise; the model is also told not to
67
- report dependency CVEs, style notes, speculation, or config-leak-only risks.
68
-
69
- ## Extending
70
-
71
- Add a vulnerability class by dropping a new `codejury/data/rules/<class>.md` with
72
- the standard frontmatter (title, impact, tags, triggers) and vulnerable/secure
73
- examples. It is data; no code change needed.
File without changes
File without changes
File without changes
File without changes