odooscan
A quality and security scanner for Odoo modules, written in Rust. It parses Python with ruff's
parser, and XML and CSV natively. It then builds one index of every model, field, method, XML id,
view and access rule across the modules it is given, so rules can check what a single-file linter
cannot. For example, it can tell you that a view names a field its model lacks, or that an XML id
belongs to a module missing from depends.
uv tool install odooscan # or: pip install odooscan
oscn check path/to/custom-addons --addons-path ~/repos/odoo/odoo,~/repos/odoo/enterprise
The wheels hold a prebuilt binary for Linux (glibc and musl), macOS and Windows; cargo build --release builds target/release/oscn anywhere else.
The command is oscn. check reports on the modules found under the given paths. --addons-path holds what those
modules build on. It is indexed but never reported on, and an Odoo source checkout stands for its
addons and odoo/addons directories. The variable ODOOSCAN_ADDONS_PATH sets the same thing.
Without base on the addons path, the rules marked needs_index in src/rules.rs are off and a
notice says so.
Other options:
--format githuband--format gitlabare for CI (see below);jsonandsariffor other tools.--select OD3and--ignore OD111filter by code prefix.--exclude migrations/,tests/hides findings in files matching gitignore-style patterns.--statisticsprints counts per rule.
The exit status is 1 when anything is reported, and 2 when the settings are invalid.
Configuration
oscn check reads the nearest odooscan.toml, or pyproject.toml with a [tool.odooscan]
table, in the current directory or above it; --config names one instead. Its keys are the
check flags, and a flag or ODOOSCAN_ADDONS_PATH replaces the key of the same name.
[tool.odooscan]
addons-path = ["../odoo", "../enterprise"]
odoo-version = "18.0"
ignore = ["OD111"]
exclude = ["/legacy", "migrations/"]
baseline = "odooscan-baseline.json"
Paths in the file are relative to it, and so are anchored exclude patterns (those with a slash
before the end, such as /legacy). An unanchored one, such as migrations/, matches at any depth.
Excluded files are still indexed: they only go unreported.
In CI
The scan needs the Odoo sources your modules build on. A shallow sparse clone into a hidden
directory is enough, and module discovery skips hidden directories. Leaving out translations,
static assets and tests makes it about 20 MB instead of 190 MB, with the same index. On GitHub, --format github
annotates the pull request, with no need for the Advanced Security that SARIF upload requires on a
private repository:
- uses: actions/checkout@v7
- uses: actions/checkout@v7
with:
repository: odoo/odoo
ref: "18.0"
path: .odoo
fetch-depth: 1
filter: blob:none
sparse-checkout-cone-mode: false
sparse-checkout: |
/addons/
/odoo/addons/
!**/i18n/
!**/static/
!**/tests/
persist-credentials: false
- uses: astral-sh/setup-uv@v10
- run: uvx --from odooscan oscn check --addons-path .odoo --format github
On GitLab, --format gitlab writes a Code Quality report for the merge request:
odooscan:
image: python:3.13
script:
- git clone --depth 1 --branch 18.0 --filter=blob:none --no-checkout https://github.com/odoo/odoo .odoo
- git -C .odoo sparse-checkout set --no-cone '/addons/' '/odoo/addons/' '!**/i18n/' '!**/static/' '!**/tests/'
- git -C .odoo checkout 18.0
- pip install odooscan
- oscn check --addons-path .odoo --format gitlab > gl-code-quality-report.json
artifacts:
when: always
reports:
codequality: gl-code-quality-report.json
Pin odooscan to a version, and the actions to commit SHAs, in a real pipeline.
Series
Each rule declares the Odoo series it applies to, and every module is checked against its own
series. The series is the first two parts of a five-part manifest version, so 18.0.1.2.0 means
18.0. Pass --odoo-version 18.0 for modules whose version does not name one. Those modules
otherwise get only the rules that carry no range. oscn rules --odoo-version 18.0 lists the
rules for a series.
Adopting on an existing codebase
oscn check --write-baseline records every current finding in odooscan-baseline.json beside the
configuration file, and later runs given --baseline odooscan-baseline.json (or the baseline
key) report only new ones. A finding is recorded by file, code and message, not line, so edits
around it do not bring it back. When findings are fixed, a notice says so; write the baseline again
to drop them and keep the file shrinking.
Suppressing a finding
Write odooscan: ignore[OD103] in a comment, or noqa: OD103. A trailing comment covers its own
line, and a comment alone on a line covers the next one. odooscan: ignore without codes covers
every rule. XML takes the same text inside <!-- -->.
Layout
crates/odooscan_core/src/project.rsfinds modules, parses every file in parallel, and keeps per-file facts.python.rs,xml.rs,csvdata.rsandmanifest.rsextract those facts and raise the single-file rules.
index.rsmerges the facts. It resolves fields through_inherit,_inheritsanddelegate=True, related comodels, view inheritance, and the dependency scope of each module.checks.rsholds the cross-file rules.rules.rsis the registry: code, series range, severity and category.crates/odooscanis the CLI.
Testing
cargo test runs a snapshot over crates/odooscan_core/tests/fixtures. That fixture is a small
core (base, mail) plus custom modules written to trigger every rule; review changes with
cargo insta review. The false-positive oracle is Odoo itself: a scan of core must report exactly
the findings recorded in tests/oracle/, as CONTRIBUTING.md describes.
Metadata
Release files for odooscan 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| odooscan-0.3.0.tar.gz | 50.1 kB | Without provenance | Details for odooscan-0.3.0.tar.gz |
Built distributions (wheels)
Total release size: 15.0 MB
Release files / odooscan-0.3.0.tar.gz
| Download URL | odooscan-0.3.0.tar.gz |
|---|---|
| Size | 50.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
60c6c98171765f74f883c6236a593de4beb50357da5e30bcb2c6c75025c19a31
|
|
BLAKE2b-256 checksum How to use checksums |
04bd060a5345771671d3272e641e9ce73a6a0bfcb12007d32c925db579f80b47
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / odooscan-0.3.0-py3-none-win_amd64.whl
| Download URL | odooscan-0.3.0-py3-none-win_amd64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
bba7358443c43dd62b9665f3810eaf8716875821b5617ddd3a3b94f64df10da0
|
|
BLAKE2b-256 checksum How to use checksums |
2bfbed95d9d50c780172dc33947a0fd179bf2b960d109e3481b6fa810d2152b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / odooscan-0.3.0-py3-none-musllinux_1_2_x86_64.whl
| Download URL | odooscan-0.3.0-py3-none-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 2.3 MB |
| Tags | Linux musl 1.2+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
55c871cc3b7ade144d9983664584a7e03dfd13bea6ac0b81aac9ec7db79eb30c
|
|
BLAKE2b-256 checksum How to use checksums |
905411c9217d4a1523b23ab6034219cc5a9e360c7ecf0b18b73171c5803b8f71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / odooscan-0.3.0-py3-none-musllinux_1_2_aarch64.whl
| Download URL | odooscan-0.3.0-py3-none-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | Linux musl 1.2+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
524cd5c2537fdfb03f43e2e86568608a9fc5b3b43ee2f035c2f6350df891066f
|
|
BLAKE2b-256 checksum How to use checksums |
8f2c05dbdf07249df919d1d273722a23d0ad91df98b4a7234508fe05782aa3f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / odooscan-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | odooscan-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
b909ed8827826809009ee20a329e98bf36c3f30feb4cda4fb33df9b3fd1a873c
|
|
BLAKE2b-256 checksum How to use checksums |
a259f09eed925095bfeabe12e4417a7a106e0a93ed1b727bdd54fdb862c1966b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / odooscan-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | odooscan-0.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
4e1be460442fdf1c5ef2e687fc858268403a1dd5808f014c5ee7917887d590b0
|
|
BLAKE2b-256 checksum How to use checksums |
2028960e6377276c2d5e9e3bbae789dbbe5c7d181bbd97b80c3783d77a0747fb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / odooscan-0.3.0-py3-none-macosx_11_0_arm64.whl
| Download URL | odooscan-0.3.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.0 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
a98d0cf41019d48da5284642d9dec626271ed941965d9a79bddb9d7fd7954e68
|
|
BLAKE2b-256 checksum How to use checksums |
f58690bceb4d3e74e080677b02bd74183a40a2393ba59d488afb4e5d7ec6eb46
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / odooscan-0.3.0-py3-none-macosx_10_12_x86_64.whl
| Download URL | odooscan-0.3.0-py3-none-macosx_10_12_x86_64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | Python 3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
f5e629b4cc80c947c5303d5cc1be8228ce096d945e3c1e8384f56e17b67aa123
|
|
BLAKE2b-256 checksum How to use checksums |
169a2e17a50b07aa08047c6ab9c264314b6d1e11f689a7fdd54a293734cdcd8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.6 {"installer":{"name":"uv","version":"0.13.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for odooscan 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.