ExportXMLWordPrintable

    • 937.3.6

      Summary

       

      CloudWebhookManager.shouldUpdate() always triggers secret update causing webhook cache to be ineffective

      • Affects Version: 937.3.2 (introduced in PR #1126 / JENKINS-76184)
      • Environment: Bitbucket Cloud with hook signature enabled and webhook caching enabled

        

      When both "Enable hook signature" and "Enable cache" are configured on the Bitbucket Cloud endpoint, the webhook cache (introduced in JENKINS-76184) is never effective. Every organization folder scan triggers a webhook update for every
         repository, which immediately evicts the cache entry. The stats() output always shows "Repositories webhooks: No entry.".

       

      Possible Root Cause

         Bitbucket Cloud's REST API (GET /2.0/repositories/{owner}/{repo}/hooks) does not return the secret value in the response — it only returns "secret_set": true. The BitbucketCloudWebhook object deserialized from this response has getSecret()
         == null.

      In CloudWebhookManager.shouldUpdate():

         if (!Objects.equal(current.getSecret(), expected.getSecret())) {
             current.setSecret(expected.getSecret());
             logger.info(() -> "Update webhook " + current.getUuid() + " signature secret");
             update = true;
         }
      

       

         This always evaluates to !Objects.equal(null, "actual-secret-value") → true, causing:

         1. An unnecessary PUT request to Bitbucket on every repo during every scan
         2. Cache eviction in update() method after the PUT
         3. The cache feature from JENKINS-76184 provides no benefit when hook signatures are enabled

      Steps to Reproduce

         1. Configure a Bitbucket Cloud endpoint with:
           - "Enable hook signature" checked with a valid secret credential
           - "Enable cache" checked

         2. Create an organization folder pointing to a workspace with repositories
         3. Trigger an organization folder scan
         4. Observe logs showing "Update webhook {uuid} signature secret" for every repo
         5. Check stats — shows "Repositories webhooks: No entry."
         6. Trigger a second scan — same behavior repeats

         Confirmation:

         Calling the Bitbucket API directly confirms the secret field is null in GET responses while secret_set: true is present:

      {    
          "uuid": "{cba5af76-...}",
          "secret_set": true,
          "secret": null,
          ...
      }
      

      Suggestions

      Since the API never returns the actual secret value, there's no way to detect a credential rotation purely from the API response.

      Skip comparison when secret is already set — Only push the secret if secret_set is false. Secret rotation would require clearing the cache (via the UI "Clear Caches" button or cache expiry). This is the simplest change:

         if (expected.getSecret() != null && !current.isSecretSet()) {
              current.setSecret(expected.getSecret());
              logger.info(() -> "Set webhook " + current.getUuid() + " signature secret");
              update = true;
         }
      

      Use cache presence as the gate — If the webhook's cache entry exists (meaning it was already processed successfully in this cache window), skip the secret comparison. After cache expiry or manual clear, the secret gets re-pushed once.
         This aligns with the existing cache TTL mechanism.

      Impact

      Organizations with hook signatures enabled and 500+ repositories (the exact use case JENKINS-76184 was designed for) get no benefit from the caching feature and continue hitting rate limits.

      Related: JENKINS-76184, PR #1126

            Assignee:
            Nikolas Falco
            Reporter:
            Soham Jambhekar
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: