Action required: Atlassian Connect vulnerability allows bypass of app qsh verification via context JWTs

Here is my take at making this more digestible:

For all Connect apps

Adjust descriptor of all your connect apps
Regardless of whether you need to actually make any changes to the logic of your apps, you will need to add the following to your descriptor:

"apiMigrations": {
     "context-qsh": true
  }

This is mandatory for all Connect apps to be implemented before June 7th, 2021. Failure to do so will result in a vulnerability report on the Security dashboard with an SLA of 4 weeks to comply. Failure to mitigate the vulnerability might result in delisting of your app.

For Connect apps running on Atlassian Connect Express (ACE)

Endpoints that serve iframe content, webhooks or lifecycle events
Atlassian will add a valid QSH to all endpoints that serve server-side rendered HTML content for iframes, webhooks or app lifecycle events (except for the first installation). Basically any URL that is listed in your descriptor. Those endpoints will need to enforce QSH validation. For these endpoints, you probably do not need to change anything, as you will already have addon.authenticate() in the middleware, like this:

app.get('/path/to/webitem', addon.authenticate(), (req, res) => {
  // return server-side rendered HTML
});

API endpoints that are called from front-end
Calls to these endpoints do not have valid QSH claims because the JWT token is generated on the front-end without any context using AP.context.getToken().

For these endpoints, which you can identify in your front-end code, you will need to disable JWT verification by changing the code from addon.authenticate() to addon.authenticate(true):

app.get('/path/to/api/endpoint', addon.authenticate(true), (req, res) => {
  // will probably return some JSON
});

For Connect apps running on Atlassian Spring Boot
Update to the latest version of Atlassian Spring Boot.

Endpoints that serve iframe content, webhooks or lifecycle events
Atlassian will add a valid QSH to all endpoints that serve server-side rendered HTML content for iframes, webhooks or app lifecycle events (except for the first installation). Basically any URL that is listed in your descriptor. Those endpoints will need to enforce QSH validation. For these endpoints, you do not need to change anything.

API endpoints that are called from front-end
Calls to these endpoints do not have valid QSH claims because the JWT token is generated on the front-end without any context using AP.context.getToken().

For these endpoints, which you can identify in your front-end code, you will need to add @ContextJWT annotation:

@ContextJwt
@RequestMapping(value = "/path/to/api/endpoint", method = RequestMethod.GET)
public ResponseEntity<Void> exampleEndpoint(@AuthenticationPrincipal AtlassianHostUser hostUser) {
  // ...
  return ResponseEntity.ok().build();
}

For Connect apps running on custom implementation

Endpoints that serve iframe content, webhooks or lifecycle events
Atlassian will add a valid QSH to all endpoints that serve server-side rendered HTML content for iframes, webhooks or app lifecycle events (except for the first installation). Basically any URL that is listed in your descriptor. Those endpoints will need to enforce QSH validation. For these endpoints, you probably do not need to change anything as you are already doing it (or decided not to).

API endpoints that are called from front-end
Calls to these endpoints do not have valid QSH claims because the JWT token is generated on the front-end without any context using AP.context.getToken().

For these endpoints, which you can identify in your front-end code, you will need to add QSH validation and enforce it by ensuring the qsh claim is part of the JWT and is set to value context-jwt.

21 Likes