Security

Kaneo: Gitea token and webhook secret exposed to workspace members

Kaneo - Gitea integration access token and webhook secret exposed to any workspace member (GHSA-43pc-xpv9-6566)

PUBLISHED SEVERITY HIGHSTATUS PatchedGHSA-43pc-xpv9-6566
Patched

Fixed in Kaneo 2.13.0 (2026-08-05) by commit 3ac5aa9: the external-link route now returns only the integration id and type. Track the fix at usekaneo/kaneo@3ac5aa9.

Product
Kaneo (self-hosted project management, usekaneo/kaneo) in usekaneo/kaneo
Affected versions
Kaneo before 2.13.0 with a Gitea integration configured. The Gitea integration first shipped in 2.5.0 (2026-04-01). Fixed in 2.13.0 (2026-08-05).
Severity
HIGH
Status
Patched
Weaknesses
  • CWE-200Exposure of Sensitive Information to an Unauthorized Actor
  • CWE-522Insufficiently Protected Credentials
As filed on the advisory.
GitHub advisory
GHSA-43pc-xpv9-6566
Published by the maintainer on 2026-08-05
CVE
Pending (requested from GitHub)
Published
Credit
Finder: Aaron Elijah Mars of Aeon. Tool: Aeon (https://www.aeon.fun).

What users should do now

Upgrade to Kaneo 2.13.0 or later. If you ran a Gitea integration on an older version, treat its secrets as leaked, even after upgrading.

  1. Upgrade Kaneo to 2.13.0 or later.
  2. Revoke the Gitea personal access token the integration used and create a new one.
  3. Rotate the Gitea webhook secret.
  4. Reconfigure the integration in Kaneo with the new values.
  5. If you cannot upgrade yet, remove the Gitea integration. That clears the exposed config, but also turns the integration off.

Rotation matters most on instances where not every workspace member is fully trusted, for example with open registration or outside collaborators.

Summary

Kaneo links tasks to issues and pull requests in Gitea. The Gitea integration stores its settings, including a Gitea personal access token (accessToken) and the secret used to sign inbound webhooks (webhookSecret), as plaintext JSON in the config column of the integration table. Before 2.13.0, GET /api/external-link/task/:taskId loaded each external link with its whole integration row attached and returned it as is. The route only checked that the caller was a member of the task's workspace, so any member, down to the viewer role, could read both secrets by opening any task with a linked Gitea issue or pull request.

Affected versions

Kaneo before 2.13.0, on instances with at least one Gitea integration and at least one task linked to a Gitea issue or pull request. The Gitea integration first shipped in 2.5.0 (2026-04-01), so in practice 2.5.0 through 2.12.2 are affected. Fixed in 2.13.0 (2026-08-05). GitHub integrations are not affected: they store an installationId and no secret. Instances with no Gitea integration are not affected.

Impact

  • Gitea access token. Anyone holding it can act on the Gitea server with whatever access the token carries. Depending on its scopes, that can include reading private repositories and writing to issues, pull requests or code.
  • Webhook secret. Kaneo checks an HMAC signature on inbound Gitea webhooks with this secret. Knowing it lets an attacker forge webhook deliveries that Kaneo accepts as genuine, and so change task state through the integration.
  • Low bar. Only workspace membership is needed. The dedicated Gitea integration getter masks the token, but this route bypassed that masking.

Affected code

Permalinks at 6fc3f44, the parent of the fix commit.

Fix

  • 3ac5aa9 ("stop returning integration secrets from the external-link route") makes the route select only the integration id and type, which is all the web client reads, and drops config from the client type. It adds an integration test that a viewer gets neither secret. Released in 2.13.0.
  • The fix is still in place on main at 39e7a34, with a code comment warning never to widen the selection.
  • Upgrading does not undo a past leak. Rotate the Gitea token and webhook secret as described above.

Detection (for defenders)

In Kaneo API logs from before the upgrade, look for GET /api/external-link/task/ requests from accounts that had no reason to view those tasks, especially viewer members or recently added users. On the Gitea side, review activity by the account that owns the integration token for actions Kaneo would not make. Compare Kaneo task changes that came in through Gitea webhooks with the delivery history of the webhook in Gitea; a change with no matching delivery points to a forged request. A working exploit is withheld.

Timeline

  1. Kaneo 2.5.0 released, the first release with the Gitea integration.
  2. After a private report from Aeon, the maintainer commits the fix (3ac5aa9) and releases Kaneo 2.13.0.
  3. Maintainer publishes GHSA-43pc-xpv9-6566, crediting Aeon as reporter.
  4. We ask for a CVE ID in usekaneo/kaneo#1973; the maintainer requests one from GitHub the same day.
  5. Public write-up.

Credit

Finder: Aaron Elijah Mars of Aeon. Tool: Aeon.

References