omamori 0.1.4 → 0.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +19 -7
- data/README.md +185 -60
- data/README_ja.md +187 -57
- data/demo/ai_analysis_vulnerability.rb +3 -3
- data/demo/csrf_vulnerability.rb +1 -1
- data/demo/eval_vulnerability.rb +1 -1
- data/demo/idor_vulnerability.rb +2 -2
- data/demo/insecure_cookie_vulnerability.rb +1 -1
- data/demo/open_redirect_vulnerability.rb +1 -1
- data/demo/static_analysis_vulnerability.rb +1 -1
- data/demo/xss_vulnerability.rb +1 -1
- data/exe/omamori +2 -2
- data/lib/omamori/ai_analysis_engine/checklist_scanner.rb +143 -0
- data/lib/omamori/ai_analysis_engine/cli_clients/base.rb +43 -0
- data/lib/omamori/ai_analysis_engine/cli_clients/claude_code_client.rb +35 -0
- data/lib/omamori/ai_analysis_engine/cli_clients/codex_client.rb +47 -0
- data/lib/omamori/ai_analysis_engine/diff_splitter.rb +17 -4
- data/lib/omamori/ai_analysis_engine/fallback_client.rb +23 -0
- data/lib/omamori/ai_analysis_engine/judge_client.rb +45 -0
- data/lib/omamori/ai_analysis_engine/llm_client.rb +71 -0
- data/lib/omamori/ai_analysis_engine/prompt_manager.rb +72 -12
- data/lib/omamori/ai_analysis_engine/ruby_llm_context.rb +23 -0
- data/lib/omamori/ai_analysis_engine/sub_checks/audit_log_missing.yml +12 -0
- data/lib/omamori/ai_analysis_engine/sub_checks/csrf.yml +22 -0
- data/lib/omamori/ai_analysis_engine/sub_checks/insecure_deserialization_rce.yml +9 -0
- data/lib/omamori/ai_analysis_engine/sub_checks/insufficient_encryption.yml +19 -0
- data/lib/omamori/ai_analysis_engine/sub_checks/mass_assignment.yml +19 -0
- data/lib/omamori/ai_analysis_engine/sub_checks/open_redirect.yml +17 -0
- data/lib/omamori/ai_analysis_engine/sub_checks/sql_injection.yml +20 -0
- data/lib/omamori/ai_analysis_engine/sub_checks/xss.yml +37 -0
- data/lib/omamori/ai_settings.rb +273 -0
- data/lib/omamori/config.rb +71 -72
- data/lib/omamori/core_runner.rb +332 -359
- data/lib/omamori/doctor.rb +95 -0
- data/lib/omamori/parallel.rb +24 -0
- data/lib/omamori/report_generator/console_formatter.rb +48 -42
- data/lib/omamori/report_generator/html_formatter.rb +6 -6
- data/lib/omamori/report_generator/json_formatter.rb +1 -1
- data/lib/omamori/setup_files.rb +260 -0
- data/lib/omamori/static_analysers/brakeman_runner.rb +7 -7
- data/lib/omamori/static_analysers/bundler_audit_runner.rb +8 -6
- data/lib/omamori/version.rb +2 -2
- data/lib/omamori.rb +11 -11
- metadata +45 -26
- data/lib/omamori/ai_analysis_engine/gemini_client.rb +0 -71
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f3533e1d6c54d0dc29d8c7eb569e9931cdd55b8214180e7380f3cf7080c0caa
|
|
4
|
+
data.tar.gz: ed4ca270d8a0d490b1c756e6508509609af5c495094ea3dd81e196baa91e6d66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fa320c3f0bf6f02cf9f76888a691b24322101e3c8c6787a3e1397f66445248e8edb8a8f6265ceae6870b4fd4aed966dc70425ae02d83d736b6ac972b327d4ce
|
|
7
|
+
data.tar.gz: 7a6cad8d83abeb40a5e833aadebf3ac0ee10a5629c64df88707852cdc11b42c55b06131dfe5299b0e3393370785b8237ceee74637a1f11f61382c1f687e55e91
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.2.0 (2026-10-25)
|
|
4
|
+
|
|
5
|
+
### Breaking changes
|
|
6
|
+
|
|
7
|
+
- **There is no default reporter.** Choose one with `omamori init --reporter ...` (or `--reporter` on `omamori scan`). Without one, `omamori scan` stops and shows how to run `init`. An 0.1 config that only sets `api_key` keeps using Gemini, now with `gemini-3.8-flash`.
|
|
8
|
+
- `omamori init` takes the settings as flags (`--reporter`, `--reporter-model`, `--classifier`, `--classifier-model`, `--language`, `--ci`, `--force`) and requires `--reporter`. It no longer overwrites an existing `.omamorirc` unless `--force` is given.
|
|
9
|
+
- Without a classifier, all checks are now run by default (0.1 ran 6 main checks). The checks are now 35: `server_error_information_exposure` is merged into `overly_detailed_errors`, and `dependency_trojan_package` (malicious packages) is no longer judged by AI. Use bundler-audit (run by omamori) for known vulnerable versions, and a scanner with a malicious-package database (such as OSV-Scanner or GitHub dependency review) for malicious packages.
|
|
10
|
+
- Checks about something being absent (CSP and other security headers, production settings, two-factor authentication, password policy, audit logging) now ask whether the change weakens or removes an existing protection, instead of whether the application has it.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Classifier**: a fast decision model (TypeSafe Jev, OpenAI Decisions, or one on Ollama) checks each risk as a yes/no question, and only the flagged checks are sent to the reporter. Several risks are also asked as concrete sub-checks. The default threshold is 0.5.
|
|
15
|
+
- **Reporter choice**: any provider RubyLLM supports, or a Claude Code (`claude -p`) / Codex (`codex exec`) subscription. A fallback reporter (`reporter.fallback`) is asked when the reporter refuses or fails.
|
|
16
|
+
- `omamori doctor`: sends the configured classifier and reporters one small request each and says what is missing.
|
|
17
|
+
- `omamori scan --base REF`: scans the diff between REF and HEAD (what a pull request contains).
|
|
18
|
+
- CI configurations generated by `init --ci` / `ci-setup` pass the API keys your classifier and reporter need.
|
|
19
|
+
- An eval set (`evals/`) with AI-written cases, a holdout set, real security fixes from the GitHub Advisory Database, and ordinary commits for measuring false alarms.
|
|
20
|
+
- README sections on getting started and on setting omamori up with an AI agent.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- A reporter refusing to analyze content (Gemini sometimes refuses security analysis) was shown as "no risks". Refused or failed checks are now kept as flags, so nothing is silently passed.
|
|
25
|
+
- The `ci-setup` command was not recognized.
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
omamori (0.
|
|
4
|
+
omamori (0.2.0)
|
|
5
5
|
brakeman (~> 7.0)
|
|
6
6
|
bundler-audit (~> 0.9.2)
|
|
7
7
|
colorize (~> 0.8)
|
|
8
8
|
dotenv (~> 2.0)
|
|
9
|
-
|
|
9
|
+
ruby_llm (~> 2.1)
|
|
10
10
|
|
|
11
11
|
GEM
|
|
12
12
|
remote: https://rubygems.org/
|
|
13
13
|
specs:
|
|
14
14
|
ast (2.4.3)
|
|
15
|
+
base64 (0.3.0)
|
|
15
16
|
brakeman (7.0.2)
|
|
16
17
|
racc
|
|
17
18
|
bundler-audit (0.9.2)
|
|
@@ -24,14 +25,17 @@ GEM
|
|
|
24
25
|
faraday-net_http (>= 2.0, < 3.5)
|
|
25
26
|
json
|
|
26
27
|
logger
|
|
27
|
-
faraday-multipart (1.
|
|
28
|
+
faraday-multipart (1.2.0)
|
|
28
29
|
multipart-post (~> 2.0)
|
|
29
30
|
faraday-net_http (3.4.0)
|
|
30
31
|
net-http (>= 0.5.0)
|
|
32
|
+
faraday-retry (2.4.0)
|
|
33
|
+
faraday (~> 2.0)
|
|
31
34
|
json (2.12.0)
|
|
32
35
|
language_server-protocol (3.17.0.5)
|
|
33
36
|
lint_roller (1.1.0)
|
|
34
37
|
logger (1.7.0)
|
|
38
|
+
marcel (2.1.0)
|
|
35
39
|
multipart-post (2.4.1)
|
|
36
40
|
net-http (0.6.0)
|
|
37
41
|
uri
|
|
@@ -71,16 +75,24 @@ GEM
|
|
|
71
75
|
rubocop-ast (1.44.1)
|
|
72
76
|
parser (>= 3.3.7.2)
|
|
73
77
|
prism (~> 1.4)
|
|
74
|
-
ruby-gemini-api (0.1.1)
|
|
75
|
-
faraday (~> 2.0)
|
|
76
|
-
faraday-multipart (~> 1.0)
|
|
77
|
-
json (~> 2.0)
|
|
78
78
|
ruby-progressbar (1.13.0)
|
|
79
|
+
ruby_llm (2.1.1)
|
|
80
|
+
base64
|
|
81
|
+
faraday (>= 1.10.0, != 2.0.0)
|
|
82
|
+
faraday-multipart (>= 1)
|
|
83
|
+
faraday-net_http (>= 1)
|
|
84
|
+
faraday-retry (>= 1)
|
|
85
|
+
json (< 4)
|
|
86
|
+
marcel (>= 1.0, < 3)
|
|
87
|
+
schematist (~> 1.1)
|
|
88
|
+
zeitwerk (~> 2)
|
|
89
|
+
schematist (1.1.0)
|
|
79
90
|
thor (1.3.2)
|
|
80
91
|
unicode-display_width (3.1.4)
|
|
81
92
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
|
82
93
|
unicode-emoji (4.0.4)
|
|
83
94
|
uri (1.0.3)
|
|
95
|
+
zeitwerk (2.8.3)
|
|
84
96
|
|
|
85
97
|
PLATFORMS
|
|
86
98
|
ruby
|
data/README.md
CHANGED
|
@@ -9,59 +9,111 @@ However, please note that this gem is merely a "protective charm" and does not g
|
|
|
9
9
|
It might help prevent vulnerabilities that could occur even after human review.
|
|
10
10
|
|
|
11
11
|
Caution:
|
|
12
|
-
AI analysis can uncover vulnerabilities that static analysis alone might miss, but
|
|
13
|
-
Running the analysis multiple times may help reduce false negatives.
|
|
14
|
-
|
|
12
|
+
AI analysis can uncover vulnerabilities that static analysis alone might miss, but LLM results tend to vary from run to run.
|
|
15
13
|
|
|
16
14
|
## Features
|
|
17
15
|
|
|
18
|
-
- Scan staged changes (`git diff --staged`), the entire codebase, or specified files and directories
|
|
16
|
+
- Scan staged changes (`git diff --staged`), a branch diff (`--base`), the entire codebase, or specified files and directories.
|
|
17
|
+
- Fast checklist: each of 35 vulnerability types is checked as a yes/no question by a decision model (TypeSafe Jev, OpenAI Decisions, ...), and an LLM writes a detailed report only for the flagged checks.
|
|
18
|
+
- Choose the classifier and the reporter independently. The reporter can be any API RubyLLM supports (Gemini, Claude, OpenAI, ...) or a Claude Code (`claude -p`) / Codex (`codex exec`) subscription.
|
|
19
19
|
- Integrates with static analysis tools like Brakeman and Bundler-Audit.
|
|
20
|
-
- Utilizes the Gemini API for advanced code analysis to detect vulnerabilities.
|
|
21
20
|
- Supports multiple report formats (console, HTML, JSON).
|
|
22
|
-
-
|
|
23
|
-
-
|
|
21
|
+
- `omamori init` runs with flags only and `omamori doctor` checks the setup, so an AI agent can set omamori up for you.
|
|
22
|
+
- Generates GitHub Actions / GitLab CI configuration.
|
|
23
|
+
- An eval set (`evals/`) for measuring detection accuracy.
|
|
24
|
+
- Configuration via a `.omamorirc` file, and exclusions via a `.omamoriignore` file.
|
|
24
25
|
|
|
25
|
-
##
|
|
26
|
+
## How It Works
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
Omamori's AI analysis has two roles.
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```
|
|
30
|
+
- **Classifier:** A fast decision model that checks each of the 35 risks as a yes/no question, such as TypeSafe Jev or OpenAI Decisions. Optional.
|
|
31
|
+
- **Reporter:** The LLM that writes vulnerability reports. Without a classifier, the reporter checks every risk itself in one prompt.
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
With a classifier, a scan works like this:
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
1. The diff is split per file. For each file, all checks (35 by default) are sent to the classifier in a single request. Files are processed in parallel.
|
|
36
|
+
2. Checks whose probability is below the threshold pass immediately.
|
|
37
|
+
3. Only the remaining checks are sent to the reporter, which writes a report following that vulnerability's detection steps.
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
The questions sent to the classifier contain the same vulnerability definitions and detection steps that the reporter receives. For XSS, SQL injection, mass assignment, CSRF, open redirect, missing audit logging, insufficient encryption, and insecure deserialization, the classifier also answers sub-checks: concrete patterns that alone make the risk real (for XSS, for example, "is a URL from users put into `href` without checking its scheme?"). The highest probability among the overall question and its sub-checks is used, and the matched sub-checks are passed on to the reporter.
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
gem install omamori
|
|
43
|
-
```
|
|
41
|
+
Risks about something being absent (CSP and other security headers, production settings, two-factor authentication, password policy, audit logging) are judged as "does this change weaken or remove an existing protection?". Whether the application had the protection in the first place cannot be told from a diff that does not touch it. If the classifier fails for a file, every check for that file is escalated to the reporter. If the reporter cannot write a report, the classifier's flag is kept in the results, so nothing is silently skipped.
|
|
44
42
|
|
|
45
|
-
##
|
|
43
|
+
## Getting Started
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
1. Add omamori to your Gemfile and install it.
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
```ruby
|
|
48
|
+
gem 'omamori', group: :development, require: false
|
|
49
|
+
```
|
|
50
50
|
|
|
51
|
-
```bash
|
|
52
|
-
|
|
53
|
-
```
|
|
51
|
+
```bash
|
|
52
|
+
bundle install
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
2. Choose a reporter and write the config file. The provider and model are given as flags (there are no interactive questions).
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
```bash
|
|
58
|
+
bundle exec omamori init --reporter claude_code # Claude Code subscription (claude -p)
|
|
59
|
+
bundle exec omamori init --reporter codex # Codex subscription (codex exec)
|
|
60
|
+
bundle exec omamori init --reporter anthropic --reporter-model claude-sonnet-5-5 # Any API RubyLLM supports
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Add `--classifier typesafe` to use a classifier, `--language ja` for reports in Japanese, and `--ci github_actions` (or `gitlab_ci`) to also generate a CI configuration. This writes `.omamorirc` and `.omamoriignore`, then prints the next steps (such as the environment variables to set). An existing `.omamorirc` is not overwritten unless you pass `--force`.
|
|
64
|
+
|
|
65
|
+
3. Set the environment variables it printed, and check the setup.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
bundle exec omamori doctor
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This sends the classifier and the reporter one small request each, and says what is missing (an API key, or installing or logging in to a CLI) and how to fix it. It exits with 0 when everything works and 1 otherwise.
|
|
72
|
+
|
|
73
|
+
4. Scan.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
bundle exec omamori scan --base main
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
There is no default reporter. If neither `.omamorirc` nor `--reporter` sets one, `omamori scan` stops and shows how to run `init`.
|
|
80
|
+
|
|
81
|
+
### API Keys
|
|
82
|
+
|
|
83
|
+
API keys are passed through environment variables, named after RubyLLM's settings in upper case (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, `OPENROUTER_API_KEY`, `TYPESAFE_API_KEY` for the Jev classifier, ...). `omamori init` prints the ones your setup uses. The `claude_code` / `codex` reporters use the installed CLI's login, so no API key is needed.
|
|
84
|
+
|
|
85
|
+
Code diffs are sent to the classifier and reporter providers you choose. For code that must not leave your environment, choose a model that runs locally, such as one on Ollama.
|
|
86
|
+
|
|
87
|
+
## Setting Up with an AI Agent
|
|
88
|
+
|
|
89
|
+
When you ask an AI coding agent (Claude Code, Codex, ...) to set up omamori, it can follow these steps:
|
|
90
|
+
|
|
91
|
+
1. Add `gem 'omamori', group: :development, require: false` to the Gemfile and run `bundle install`
|
|
92
|
+
2. Choose the reporter: `claude_code` if the `claude` command exists, `codex` if `codex` exists. Otherwise, ask the developer which API provider and model they use
|
|
93
|
+
3. Ask the developer whether to use a classifier (`--classifier typesafe`, ...). It makes scans faster and cheaper and raises fewer false alarms, but needs that provider's API key and sends the code to that provider as well
|
|
94
|
+
4. Run `bundle exec omamori init --reporter ... [--reporter-model ...] [--classifier ...] [--language ja] [--ci github_actions]`
|
|
95
|
+
5. Ask the developer to set the environment variables it printed. Do not ask them to paste API keys into the chat, and do not write keys into files
|
|
96
|
+
6. Run `bundle exec omamori doctor`, fixing what it reports, until it exits with 0
|
|
97
|
+
7. Run `bundle exec omamori scan --base main` and report the results. If a CI configuration was generated, also tell the developer the secret names to register (printed by `init`)
|
|
98
|
+
|
|
99
|
+
## Usage
|
|
56
100
|
|
|
57
101
|
### Scanning
|
|
58
102
|
|
|
103
|
+
Any setting in `.omamorirc` can be changed for one run with flags (see Choosing the Classifier and Reporter).
|
|
104
|
+
|
|
59
105
|
Scan staged changes (default):
|
|
60
106
|
|
|
61
107
|
```bash
|
|
62
108
|
omamori scan
|
|
63
109
|
```
|
|
64
110
|
|
|
111
|
+
Scan the changes on the current branch (`main...HEAD`, i.e. what a pull request contains; useful in CI):
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
omamori scan --base main
|
|
115
|
+
```
|
|
116
|
+
|
|
65
117
|
Scan the entire codebase:
|
|
66
118
|
|
|
67
119
|
```bash
|
|
@@ -69,60 +121,101 @@ omamori scan --all
|
|
|
69
121
|
```
|
|
70
122
|
This mode respects the `.omamoriignore` file.
|
|
71
123
|
|
|
72
|
-
|
|
124
|
+
Scan specific files or directories:
|
|
73
125
|
|
|
74
126
|
```bash
|
|
75
|
-
|
|
76
|
-
bundle exec omamori scan --all --format json
|
|
127
|
+
omamori scan app/controllers/users_controller.rb app/models/user.rb config/routes.rb lib/
|
|
77
128
|
```
|
|
129
|
+
This mode also respects the `.omamoriignore` file.
|
|
78
130
|
|
|
79
|
-
|
|
131
|
+
Specify the output format (console, html, json):
|
|
80
132
|
|
|
81
|
-
|
|
133
|
+
```bash
|
|
134
|
+
omamori scan --format html
|
|
135
|
+
omamori scan --all --format json
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Run only AI analysis, skipping static analysis tools:
|
|
82
139
|
|
|
83
140
|
```bash
|
|
84
|
-
omamori scan
|
|
141
|
+
omamori scan --ai
|
|
85
142
|
```
|
|
86
143
|
|
|
87
|
-
|
|
144
|
+
### Choosing the Classifier and Reporter
|
|
145
|
+
|
|
146
|
+
Both roles are set with a `provider` and a `model`, on the command line or in `.omamorirc` (see [Configuration](#configuration)).
|
|
88
147
|
|
|
89
148
|
```bash
|
|
90
|
-
omamori scan
|
|
149
|
+
omamori scan --base main --classifier typesafe --reporter gemini --reporter-model gemini-3.8-flash # Jev decides, Gemini reports
|
|
150
|
+
omamori scan --base main --classifier typesafe --reporter claude_code # Jev decides, claude -p reports
|
|
151
|
+
omamori scan --base main --classifier openai --reporter anthropic --reporter-model claude-sonnet-5-5
|
|
152
|
+
omamori scan --reporter codex # No classifier; codex exec checks everything
|
|
91
153
|
```
|
|
92
154
|
|
|
93
|
-
|
|
155
|
+
**Do you need a classifier?** It is optional. In our measurements with `claude -p` (sonnet) as the reporter, on real security fixes from Rails applications and on ordinary commits from open-source Rails apps, the reporter alone caught at least as many vulnerabilities as the classifier pipeline. The classifier made scans faster and cheaper (the reporter is called only for flagged checks) and raised fewer false alarms on changes that look risky but are safe. Cheaper reporters have not been measured on their own.
|
|
156
|
+
|
|
157
|
+
**Classifier providers**
|
|
158
|
+
|
|
159
|
+
| provider | Decision model | API key |
|
|
160
|
+
| --- | --- | --- |
|
|
161
|
+
| `typesafe` | TypeSafe Jev (`jev-1.13.0` when `model` is omitted) | `TYPESAFE_API_KEY` |
|
|
162
|
+
| `openai` | OpenAI Decisions API (`gpt-6-luna` when `model` is omitted) | `OPENAI_API_KEY` |
|
|
163
|
+
| `ollama` | A decision model running on Ollama (such as Clef). `model` and the server's `base_url` (or `OLLAMA_API_BASE`) are required | None |
|
|
164
|
+
| `none` | No classifier (default) | None |
|
|
165
|
+
|
|
166
|
+
With `base_url`, you can point a classifier at any other server that speaks the SystemOne protocol.
|
|
167
|
+
|
|
168
|
+
**Reporter providers**
|
|
94
169
|
|
|
95
|
-
|
|
170
|
+
| provider | What it calls |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| A RubyLLM provider (`gemini`, `anthropic`, `openai`, `openrouter`, `ollama`, ...) | An API through [RubyLLM](https://rubyllm.com). `model` is required |
|
|
173
|
+
| `claude_code` | `claude -p` (subscription) with all tools disabled, in an empty temporary directory |
|
|
174
|
+
| `codex` | `codex exec` (subscription) in a read-only sandbox, in an empty temporary directory |
|
|
96
175
|
|
|
97
|
-
|
|
176
|
+
In `.omamorirc`, the reporter's `provider` can be omitted, in which case it is inferred from the model name. Set `provider` when the model is too new to be in RubyLLM's model registry.
|
|
177
|
+
|
|
178
|
+
A reporter may refuse to analyze some content (Gemini sometimes refuses security analysis). A refused check is not silently passed; the classifier's flag is kept. With a fallback reporter (`reporter.fallback`), refused or failed checks are asked again there, and only those.
|
|
98
179
|
|
|
99
180
|
```bash
|
|
100
|
-
omamori scan --
|
|
181
|
+
omamori scan --base main --classifier typesafe --reporter-fallback claude_code --reporter-fallback-model sonnet
|
|
101
182
|
```
|
|
102
183
|
|
|
184
|
+
Diffs contain code from outside sources, so `claude_code` / `codex` run without the ability to execute commands. Because subscriptions have tighter rate limits, reports are written 3 at a time when a CLI is used (change with `reporter.concurrency`).
|
|
185
|
+
|
|
103
186
|
## Configuration
|
|
104
187
|
|
|
105
188
|
The `.omamorirc` file in the project root directory allows you to customize Omamori's behavior.
|
|
106
189
|
|
|
107
|
-
Here's a detailed breakdown of the configuration options:
|
|
108
|
-
|
|
109
190
|
```yaml
|
|
110
191
|
# .omamorirc
|
|
111
192
|
# Configuration file for omamori gem
|
|
112
193
|
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
#
|
|
194
|
+
# Classifier (optional). Without it, the reporter checks every risk. Can be overridden with --classifier
|
|
195
|
+
# classifier:
|
|
196
|
+
# provider: typesafe # typesafe / openai / ollama
|
|
197
|
+
# model: jev-1.13.0 # Pin a version (not jev-latest) if you tune the threshold
|
|
198
|
+
# threshold: 0.5 # Checks at or above this probability go to the reporter
|
|
199
|
+
# concurrency: 8 # Parallel requests to the classifier
|
|
200
|
+
# base_url: https://api.typesafe.ai # Optional. Another SystemOne server
|
|
201
|
+
# api_key: ... # Optional. Environment variables (TYPESAFE_API_KEY, ...) are recommended
|
|
202
|
+
|
|
203
|
+
# Reporter (required; written by omamori init). Can be overridden with --reporter
|
|
204
|
+
reporter:
|
|
205
|
+
provider: anthropic # A RubyLLM provider, or claude_code / codex
|
|
206
|
+
model: claude-sonnet-5-5 # Required for API providers. For CLIs, omit it to use the CLI's default model
|
|
207
|
+
# concurrency: 8 # Reports written in parallel (default 3 for CLIs, 8 for APIs)
|
|
208
|
+
# command: /path/to/claude # Optional. Path to the claude_code / codex CLI
|
|
209
|
+
# api_key: ... # Optional. Environment variables (ANTHROPIC_API_KEY, ...) are recommended
|
|
210
|
+
# fallback: # Optional. Asked only when the reporter refuses or fails
|
|
211
|
+
# provider: claude_code
|
|
212
|
+
# model: sonnet
|
|
213
|
+
|
|
214
|
+
# Security checks to run (optional; default: all 35)
|
|
121
215
|
# checks:
|
|
122
|
-
# xss
|
|
123
|
-
# csrf
|
|
124
|
-
# idor
|
|
125
|
-
# ... # Add other checks as they become available
|
|
216
|
+
# - xss
|
|
217
|
+
# - csrf
|
|
218
|
+
# - idor
|
|
126
219
|
|
|
127
220
|
# Custom prompt templates (optional)
|
|
128
221
|
# prompt_templates:
|
|
@@ -145,9 +238,9 @@ model: gemini-2.5-flash-preview-04-17
|
|
|
145
238
|
# language: ja
|
|
146
239
|
```
|
|
147
240
|
|
|
148
|
-
* `
|
|
149
|
-
* `
|
|
150
|
-
* `checks`:
|
|
241
|
+
* `classifier`: `provider`, `model`, `threshold` (default 0.5), `concurrency` (default 8), `base_url`, `api_key`.
|
|
242
|
+
* `reporter`: `provider`, `model`, `concurrency`, `command`, `api_key`, `fallback` (a fallback reporter with its own `provider`, `model`, ...).
|
|
243
|
+
* `checks`: The list of security checks to run. The former `server_error_information_exposure` is merged into `overly_detailed_errors`. `dependency_trojan_package` (malicious packages) is no longer judged by AI, because it cannot be judged reliably from code: use bundler-audit (run by omamori) for known vulnerable versions, and a scanner with a malicious-package database, such as OSV-Scanner or GitHub dependency review.
|
|
151
244
|
* `prompt_templates`: Define custom prompt templates for AI analysis.
|
|
152
245
|
* `report`: Configure report output settings.
|
|
153
246
|
* `output_path`: The output directory or prefix for HTML and JSON reports.
|
|
@@ -157,16 +250,33 @@ model: gemini-2.5-flash-preview-04-17
|
|
|
157
250
|
* `bundler_audit`: Additional command-line options for Bundler-Audit.
|
|
158
251
|
* `language`: Language setting for the details provided in AI analysis reports. Defaults to English (`en`).
|
|
159
252
|
|
|
253
|
+
The older keys (`engine`, `llm`, `model`, `provider`, `api_key`, `decision`, `claude`, `codex`) and options (`--engine`, `--llm`) still work. A 0.1 config that only sets `api_key` keeps using Gemini (`gemini-3.8-flash`).
|
|
254
|
+
|
|
160
255
|
## .omamoriignore File
|
|
161
256
|
|
|
162
|
-
The `.omamoriignore` file allows you to exclude specific files and directories from the scan target. Its behavior is similar to a `.gitignore` file, but with the following considerations:
|
|
257
|
+
The `.omamoriignore` file allows you to exclude specific files and directories from the scan target. However, if the `--force-scan-ignored` option is used, the settings in this file will be ignored. Its behavior is similar to a `.gitignore` file, but with the following considerations:
|
|
163
258
|
|
|
164
259
|
* **Effective Modes:** It is only effective in `--all` mode or when scanning specified files/directories.
|
|
165
|
-
* **Ineffective Mode:** In `diff` mode (i.e., `omamori scan` without arguments), the `.omamoriignore` file is ignored. This is because `diff` mode only targets changes retrieved by `git diff`.
|
|
166
|
-
* **Format:** Each line specifies one pattern. Lines starting with `#` are treated as comments.
|
|
260
|
+
* **Ineffective Mode:** In `diff` mode (i.e., `omamori scan` without arguments, or with `--base`), the `.omamoriignore` file is ignored. This is because `diff` mode only targets changes retrieved by `git diff`.
|
|
261
|
+
* **Format:** Each line specifies one pattern. Lines starting with `#` are treated as comments.
|
|
262
|
+
* A pattern ending with `/` excludes everything under that directory (e.g., `vendor/bundle/`).
|
|
263
|
+
* Other patterns are evaluated as globs against the path relative to the project root or the file name (e.g., `*.log`, `spec/fixtures/*.rb`).
|
|
167
264
|
|
|
168
265
|
When you run the `omamori init` command, a `.omamoriignore` file pre-filled with patterns for common files and directories to ignore in a Rails project will be generated. You can edit this file as needed.
|
|
169
266
|
|
|
267
|
+
## Using in CI
|
|
268
|
+
|
|
269
|
+
Pass `--ci` to `omamori init`, or generate the configuration later from `.omamorirc`:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
omamori ci-setup --ci github_actions # .github/workflows/omamori_scan.yml
|
|
273
|
+
omamori ci-setup --ci gitlab_ci # .gitlab-ci.yml
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The generated configuration scans the branch diff with `--base` on pull requests (merge requests) and the entire codebase with `--all` otherwise. It fetches the full history so the diff can be taken. It passes the environment variables your classifier and reporter need, and prints the names of the secrets (CI/CD variables on GitLab) to register.
|
|
277
|
+
|
|
278
|
+
`claude_code` / `codex` use the CLI's login on the machine. The generated configuration does not install or log in a CLI on the CI runner: in CI, add `--reporter PROVIDER --reporter-model MODEL` to the scan command to use an API reporter, or set up the runner yourself.
|
|
279
|
+
|
|
170
280
|
## Demo Files
|
|
171
281
|
|
|
172
282
|
The `demo` directory contains example files with known vulnerabilities that can be used to demonstrate Omamori's capabilities.
|
|
@@ -181,15 +291,30 @@ To run Omamori on the demo files, you need to stage the changes in the `demo` di
|
|
|
181
291
|
```bash
|
|
182
292
|
git add demo_
|
|
183
293
|
```
|
|
184
|
-
3. Now you can run Omamori on the staged demo files:
|
|
294
|
+
3. Now you can run Omamori on the staged demo files (set it up with `omamori init --reporter ...` first):
|
|
185
295
|
```bash
|
|
186
296
|
omamori scan
|
|
187
297
|
```
|
|
298
|
+
To try a classifier (Jev):
|
|
299
|
+
```bash
|
|
300
|
+
omamori scan --classifier typesafe
|
|
301
|
+
```
|
|
188
302
|
Or to scan all files in the demo directory (after staging them):
|
|
189
303
|
```bash
|
|
190
304
|
omamori scan --all
|
|
191
305
|
```
|
|
192
306
|
|
|
307
|
+
## Measuring Detection Accuracy
|
|
308
|
+
|
|
309
|
+
`evals/` contains code changes with known answers. For each of the 35 risks there are two vulnerable changes and two "near miss" changes that look similar but are safe, plus a set of benign changes. XSS, SQL injection, mass assignment, IDOR, CSRF, and open redirect also have cases for specific patterns that are easy to miss. Use it to see how misses and false positives change when you switch the classifier or reporter.
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
bundle exec ruby evals/run.rb --classifier typesafe --runs 3
|
|
313
|
+
bundle exec ruby evals/run.rb --classifier none --reporter claude_code --reporter-model sonnet
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
See [evals/README.md](evals/README.md) for details.
|
|
317
|
+
|
|
193
318
|
## Contributing
|
|
194
319
|
|
|
195
320
|
Bug reports and pull requests are welcome on GitHub. This project is intended to be a safe, welcoming space for collaboration.
|