Ctrl K
ComunidadGuías…

SECURITY.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Security Policy

To report a security vulnerability, use
[GitHub private security advisories](https://github.com/omnigent-ai/omnigent/security/advisories/new).

Please do not open a public issue for security problems, and do not include live
credentials, tokens, or customer data in any report.

## Automated dependency CVE scanning

[Trivy CVE Scan](.github/workflows/trivy.yml) scans the repository on every pull
request, push to `main`, daily at 06:23 UTC, and manual workflow dispatch. The
scheduled scan catches newly published advisories even when dependencies have
not changed. It runs for trusted contributors too, after the existing PR
security gate permits CI to proceed.

Trivy statically scans supported dependency manifests and lockfiles, including
`uv.lock`, `pnpm-lock.yaml`, `Cargo.lock`, and `Gemfile.lock`, without installing
or executing project dependencies. Development dependencies, all severities,
and vulnerabilities without fixes are included. This is a dependency scan, not
a scan of built container images or a replacement for the contributor security
scan below. A separate `dev-tools` scan covers `dev/omnidev/Cargo.lock`, because
Trivy excludes root-level `dev/` directories from its filesystem traversal.

The initial rollout is **report-only**: vulnerabilities do not fail the Trivy
jobs, but scanner, report-generation, or upload errors do. A green check does
not mean there are no CVEs. SARIF results are published to
[Security > Code scanning](https://github.com/omnigent-ai/omnigent/security/code-scanning)
with stable categories `trivy-repository` and `trivy-dev-tools`. Source paths
resolve against the scanned directory so development-tool alerts link to files
under `dev/`. Uploading alerts does not itself configure a merge-blocking rule;
any existing repository code-scanning rules still apply.

Only the scan jobs request `security-events: write`; the contributor security
gate remains read-only. Uploads use the built-in GitHub token, including the
supported `pull_request` upload path for read-only fork tokens, never
`pull_request_target` or a personal access token. Maintainers must allow code
scanning in repository settings. Public repositories do not need a paid Code
Security license; private forks require the applicable feature access.

Open the workflow's **Trivy CVE Scan** jobs to read the tables, or download the
**trivy-cve-report-repository** and **trivy-cve-report-dev-tools** artifacts
(retained for 30 days) for text, JSON, and SARIF reports. Artifacts are uploaded
before code-scanning submission, so reports remain available if GitHub rejects
SARIF or code scanning is unavailable. An upload failure stays visible as a
failed check rather than silently hiding missing Security-tab results.

To reproduce locally with Trivy **v0.74.0**, from the repository root:

```bash
(
  set -e
  for target in . dev; do
    trivy fs --scanners vuln --include-dev-deps \
      --severity UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL --ignore-unfixed=false \
      --skip-dirs '.git,**/.venv,**/node_modules' --timeout 10m --exit-code 0 "$target"
  done
)
```

Review findings by affected lockfile, installed version, and available fix;
prioritize reachable high/critical vulnerabilities. Any future blocking
threshold or vulnerability exception should be an explicit, reviewed policy
change rather than silently hiding the baseline.

## Contributor PR security gate

CI for untrusted PRs is held behind a deterministic security scan so that
untrusted code is not checked out, built, or run on our runners — and the
Actions cache is not touched — until the diff has been vetted. It is split into
two pieces so the scan work happens only **once per PR**:

- **`.github/workflows/security-scan.yml`** — runs the deterministic scan once
  on `pull_request` and produces the `Security Scan` check.
- **`.github/workflows/security-gate.yml`** — a reusable poller run as the first
  job (`gate`) of every CI workflow (`ci`, `lint`, `e2e`, `e2e-ui`, web
  tests); the real jobs declare `needs: gate`. It does not re-scan — for an
  untrusted PR it waits for the `Security Scan` check and mirrors its result
  (failure → the dependent CI jobs are skipped); trusted authors and non-PR
  events proceed immediately.

By trust tier (GitHub `author_association`):

- **Trusted** (`OWNER` / `MEMBER` / `COLLABORATOR`) and all non-PR events
  (push, schedule, dispatch): the gate passes through instantly, no scan.
- **Returning contributor** (`CONTRIBUTOR`): the gate runs the scan; a clean
  result lets CI proceed automatically, a finding blocks all CI.
- **First-time contributor**: GitHub's native *“require approval to run fork
  pull request workflows”* repo setting already holds every workflow until a
  maintainer clicks **Approve and run**; after approval the gate's scan still
  applies.

The scan inspects the PR diff for committed secrets, secret-exfiltration shapes
(a secret-named credential source plus a network sink in one file, an
`os.environ` dump, a decode-then-exec, or a reverse shell), changes to
privileged repo config (CI workflows, `.github/MAINTAINER`, `CODEOWNERS`,
`.github/scripts`), CI-workflow misuse (`pull_request_target` + PR-head
checkout, unpinned actions), and known code-execution / obfuscation patterns
(semgrep, local ruleset). It only *statically* analyses the diff and runs with
**no secrets** on fork PRs,
and the scanner itself always runs from `main`, so a PR cannot weaken its own
scan.

This is **not** a merge-required check: it gates CI, not the merge button
directly. When enforcing, merge stays blocked transitively (the skipped
pytest/e2e checks are required) and `Maintainer Approval` remains the ultimate
gate.

It is **blocking**: a finding fails the `Security Scan` check, the pollers mirror
that failure, and the dependent CI jobs are skipped. Detectors run fail-fast, so
a clean PR must pass every one.

### Maintainer override

A maintainer can waive the scan on a specific PR with the **`skip-security-scan`**
label. The waiver is only honored when it
is *maintainer-effective*: the label is present **and** the PR author is a
maintainer, or a maintainer's latest decisive review is `APPROVED`. The label
alone does nothing — applying labels needs triage access, and the extra
maintainer check is defence in depth — so a fork contributor cannot self-waive.
The label and review state are read from the API, and the decision runs from
`should-scan.sh` on `main`, so a PR cannot edit the waiver logic.

To use it: a maintainer reviews/approves the PR and applies `skip-security-scan`;
the `Security Scan` check re-runs and passes, then the blocked CI workflows are
re-run (or the contributor pushes) so their gate jobs see the now-green scan.
The waiver stays effective across pushes while the maintainer approval stands —
remove the label (or dismiss the approval) to re-enable scanning.