Skip to content

Unauthenticated GET /repos/:owner/:repo/hooks leaks webhook target URLs for any repo #94

Description

@beardthelion

list_webhooks (crates/gitlawb-node/src/api/webhooks.rs:73) is mounted on the optional_signature read-routes group (crates/gitlawb-node/src/server.rs:344-365), takes no AuthenticatedDid, and performs no ownership or visibility check. Its siblings create_webhook and delete_webhook both call require_repo_owner; list_webhooks does not. get_repo applies no is_public filter, so private repos resolve the same as public ones.

Any unauthenticated caller who knows a repo's owner/name can therefore enumerate every webhook registered on it. Secrets are redacted to ***, but the full target url, the created_by_did, and the event subscriptions are returned. Webhook URLs routinely embed internal-infra hostnames, third-party integration endpoints, and tokens or signed params in the path or query. The deliberate secret redaction shows these records are treated as sensitive; the directly actionable URL field is left open.

Where

  • crates/gitlawb-node/src/server.rs:344-365 mounts the route under optional_signature
  • crates/gitlawb-node/src/api/webhooks.rs:73-97 handler has no auth param and no require_repo_owner
  • crates/gitlawb-node/src/api/webhooks.rs:88-90 redacts secret only
  • crates/gitlawb-node/src/db/mod.rs get_repo has no is_public predicate

Fix

Move list_webhooks into an authenticated group and add require_repo_owner (mirroring create_webhook / delete_webhook), or gate it on the repo's authorization model if collaborator read access is intended. Keep the existing secret redaction.

Related

The same optional_signature read group also carries list_protected_branches, list_replicas, and list_repo_events. If any are meant to be visibility-gated for private repos, they share this missing-gate pattern and are worth tracing together, since get_repo applies no visibility filter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    crate:nodegitlawb-node — the serving node and REST APIkind:securityVulnerability fix or hardeningsev:highMajor break or real security/trust risk, no easy workaroundsubsystem:apiNode REST API request/response surface

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions