views: enforce token app scope on /o/actions heatmap endpoint#7677
Merged
Conversation
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>
Contributor
There was a problem hiding this comment.
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.qstringintoauthorize.verify_return()in the/o/actionstoken-auth path so app restrictions are enforced. - Add new tests for app-scoped token behavior when
qstring.app_idis provided toauthorize.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. |
ArtursKadikis
approved these changes
Jun 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
countly-tokenbranch of the/o/actionsheatmap endpoint resolves the target app from the caller-suppliedapp_key, setsparams.qstring.app_idfrom it, and then callsauthorize.verify_return()without passingqstring.authorizer.verify_token()only enforces a token'sapprestriction whenoptions.qstring.app_idis present:With
qstringomitted, the app check is skipped andvalid_appstaystrue, so an app-scoped token is accepted for any app. The branch then callsgetHeatmap()directly (the token is the authorization model here), returning the target app's heatmap rows.Fix
Pass
qstringintoverify_returnso the token's app list is checked against the app resolved fromapp_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_returncaller (api/utils/rights.js), which already passesqstring. No other callers omit it.Tests
Adds a block to
test/2.api/14.authorize.token.js: an app-scoped token verifies for its ownapp_idand is rejected for a different one.🤖 Generated with Claude Code