Skip to content

views: enforce token app scope on /o/actions heatmap endpoint#7677

Merged
ar2rsawseen merged 1 commit into
masterfrom
fix/actions-token-app-scope
Jun 8, 2026
Merged

views: enforce token app scope on /o/actions heatmap endpoint#7677
ar2rsawseen merged 1 commit into
masterfrom
fix/actions-token-app-scope

Conversation

@ar2rsawseen

Copy link
Copy Markdown
Member

Summary

The countly-token branch of the /o/actions heatmap endpoint resolves the target app from the caller-supplied app_key, sets params.qstring.app_id from it, and then calls authorize.verify_return() without passing qstring.

authorizer.verify_token() only enforces a token's app restriction when options.qstring.app_id is present:

if (res.app && res.app !== "") {
    if (!Array.isArray(res.app)) { res.app = [res.app]; }
    if (options.qstring && options.qstring.app_id) {   // skipped when qstring absent
        if (res.app.indexOf(options.qstring.app_id) === -1) { valid_app = false; }
    }
}

With qstring omitted, the app check is skipped and valid_app stays true, so an app-scoped token is accepted for any app. The branch then calls getHeatmap() directly (the token is the authorization model here), returning the target app's heatmap rows.

Fix

Pass qstring into verify_return so the token's app list is checked against the app resolved from app_key. A token scoped to app A is now rejected when replayed against app B. Global-admin/unrestricted tokens and correctly-scoped requests are unaffected.

This matches the only other verify_return caller (api/utils/rights.js), which already passes qstring. No other callers omit it.

Tests

Adds a block to test/2.api/14.authorize.token.js: an app-scoped token verifies for its own app_id and is rejected for a different one.

🤖 Generated with Claude Code

The countly-token branch of /o/actions resolves the target app from the
caller-supplied app_key, sets params.qstring.app_id from it, then calls
authorize.verify_return() without passing qstring. authorizer.verify_token()
only enforces a token's app restriction when options.qstring.app_id is
present, so the restriction was skipped entirely and an app-scoped token was
accepted for any other app — returning that app's heatmap rows without a
read-permission check.

Pass qstring into verify_return so the token's app list is checked against
the app resolved from app_key. A token scoped to app A is now rejected when
replayed against app B.

Adds regression tests asserting an app-scoped token verifies for its own
app_id and is rejected for a different one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 8, 2026 11:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an authorization gap in the plugins/views implementation of the /o/actions heatmap endpoint when using countly-token: it ensures authorize.verify_return() receives params.qstring so app-scoped tokens are actually validated against the resolved app_id (derived from the provided app_key).

Changes:

  • Pass params.qstring into authorize.verify_return() in the /o/actions token-auth path so app restrictions are enforced.
  • Add new tests for app-scoped token behavior when qstring.app_id is provided to authorize.verify_return().

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
plugins/views/api/api.js Ensures token verification receives qstring so app-scoped token restrictions can be enforced for /o/actions.
test/2.api/14.authorize.token.js Adds coverage for app-scoped token acceptance/rejection based on qstring.app_id passed into verify_return.

Comment thread test/2.api/14.authorize.token.js
@ar2rsawseen ar2rsawseen merged commit 0c18922 into master Jun 8, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants