Skip to content

fix: least privilege and quoting for what reaches root - #59

Merged
grojof merged 3 commits into
mainfrom
fix/injection-privilege
Oct 8, 2026
Merged

grojof merged 3 commits into
mainfrom
fix/injection-privilege

Conversation

@grojof

@grojof grojof commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Second audit, group B: what reaches a root shell, a superuser session or the terminal. Each fix is checked by running it; the new tools/verify_privilege.py runs in CI.

  • Certificates: the paths are quoted. The files are staged, the key, certificate and chain are checked, and only then moved into place, keeping the previous files.
  • Venv pip, tar and git run as the instance user, with no login shell. pip options are refused, and babel>=2.14,<3 stays one requirement.
  • Report: reads pyvenv.cfg instead of running the instance's interpreter as root.
  • Neutralisation runs as the copy's owner role, with search_path = public. A trigger in the copy can no longer raise its own role; a negative control proves it does when the step runs as superuser. The check now fails when it sees no Odoo tables. A real Odoo 14/18 run caught this case: with a wrong search_path, the check passed while neutralising nothing.
  • /tmp: the venv replication and the wkhtmltopdf download use a private mktemp -d. The replication keeps only name==version lines and fails when pip fails.
  • Terminal: host text is printed inert, and typed control characters are refused.
  • Smaller fixes: escaped secrets are masked, the role SQL gets a unique dollar tag, exports are private and never follow a link, unit names are passed after --, and SECURITY.md is corrected.

Verified: verify_privilege, verify_data_safety and verify_secrets pass. verify_neutralisation passes with real Odoo 14 and 18 (52 checks).

OpenSpec: 2026-10-08-least-privilege-and-quoting.

Assisted-by: Claude

grojof added 3 commits October 8, 2026 14:38
- Certificates: operator paths quoted; files staged beside the live
  ones, key/cert/match/chain checked, then moved (previous kept).
- Venv packages: the venv pip runs as the instance user with no login
  shell; root only passes the requirements file on stdin; pip options
  refused; commas split only before a package name.
- Report reads pyvenv.cfg instead of running the instance interpreter;
  git runs as the instance user (git refuses root in another user's
  checkout), and both OCB origin forms are detected.
- Neutralisation and copy identity run as the copy's owner role with a
  fixed search_path, not as the superuser.
- Venv replication and wkhtmltopdf use a private mktemp directory; the
  replication keeps exact name==version lines and fails with pip.
- tar runs as the instance user for backups (manual and scheduled) and
  restores.
- Host text is sanitised before it reaches the terminal; typed control
  characters are refused; typed unit names go after --.
- mask covers escaped secrets; the role SQL uses a unique dollar tag;
  exports are new private files; run(check=True) no longer prints the
  command.
- tools/verify_privilege.py (CI) executes the certificate, download,
  venv and owner-role neutralisation steps.
…without Odoo tables

With search_path pg_catalog, public the current schema was pg_catalog, so
no rule found its table and the check passed on nothing. pg_catalog is
searched first anyway; the check now fails when the current schema has
no ir_cron. Table-existence tests are nested so PL/pgSQL never plans a
query on a missing table.
@grojof
grojof merged commit 6ee9a82 into main Oct 8, 2026
1 check passed
@grojof
grojof deleted the fix/injection-privilege branch October 8, 2026 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant