Page MenuHomePhabricator

Implement Security Response Header Filter logic outside RESTBase for PCS
Closed, ResolvedPublic

Description

Background Information

In order to deprecate RESTBase some of its logic need to be re-implemented in order to have full-feature parity. For Page Content Service one of the components is the lib/security_response_header_filter.js filter.

Possible solutions

  • Implement a shared JavaScript library and apply it to all Page Content Service endpoints.
    • It's basically a copy+paste from restbase to the other NodeJS services.
    • Relatively easy transition for NodeJS services that should install a new npm package
    • Introduce a maintenance burden for all NodeJS services that have to implement the Security Response Header Filter in the application layer
  • Implement the security response header filter in the envoy layer
    • Avoid having to re-create this as a JavaScript library and the maintenance burden of having it applied to all NodeJs services.
    • This filter makes more sense to be applied on the API Gateway / envoy layer and not in the application layer

Open questions

  • Can/Should this really be handled by envoy or any API Gateway?

Acceptance Criteria

  • Current NodeJS services that depends on lib/security_response_header_filter.js can apply this logic without RESTBase

Event Timeline

daniel triaged this task as Medium priority.Nov 22 2022, 6:41 PM
daniel raised the priority of this task from Medium to High.

Note: for Page Content Service in the mobile-html endpoint, restbase copy CSP headers from PCS.

A compatibility layer will be needed to implement a few of the other headers RESTBase implements.

Change 861459 had a related patch set uploaded (by MSantos; author: MSantos):

[mediawiki/services/mobileapps@master] WIP: port secutiryt headers from restbase

https://gerrit.wikimedia.org/r/861459

Change 865618 had a related patch set uploaded (by MSantos; author: MSantos):

[mediawiki/services/mobileapps@master] security headers for non-html/svg endpoints

https://gerrit.wikimedia.org/r/865618

Jgiannelos changed the task status from Open to In Progress.Dec 13 2022, 4:16 PM

Change 861459 merged by jenkins-bot:

[mediawiki/services/mobileapps@master] port security headers from restbase

https://gerrit.wikimedia.org/r/861459

Change 865618 merged by jenkins-bot:

[mediawiki/services/mobileapps@master] security headers for non-html/svg endpoints

https://gerrit.wikimedia.org/r/865618

This is properly deployed. Here's how to confirm it.

In order to check if header are consistent between mobileapps and restbase we need to query production with:

curl -sSL -D - https://en.wikipedia.org/api/rest_v1/page/mobile-html/Barack_Obama -o /dev/null

This will give the following output:

HTTP/2 200
content-language: en
content-type: text/html; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/Mobile-HTML/1.2.2"
vary: Accept-Encoding
cache-control: s-maxage=1209600, max-age=0, must-revalidate
access-control-allow-origin: *
access-control-allow-methods: GET,HEAD
access-control-allow-headers: accept, content-type, content-length, cache-control, accept-language, api-user-agent, if-match, if-modified-since, if-none-match, dnt, accept-encoding
access-control-expose-headers: etag
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
referrer-policy: origin-when-cross-origin
x-xss-protection: 1; mode=block
content-security-policy: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
x-content-security-policy: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
x-webkit-csp: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
content-location: https://en.wikipedia.org/api/rest_v1/page/mobile-html/Barack_Obama
server: restbase1031
date: Tue, 31 Jan 2023 01:28:02 GMT
etag: W/"1136227531/916c73c0-a0fc-11ed-b376-7e392fab3ed5"
age: 41993
x-cache: cp1079 hit, cp1089 hit/5
x-cache-status: hit-front
server-timing: cache;desc="hit-front", host;desc="cp1089"
strict-transport-security: max-age=106384710; includeSubDomains; preload
report-to: { "group": "wm_nel", "max_age": 86400, "endpoints": [{ "url": "https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0" }] }
nel: { "report_to": "wm_nel", "max_age": 86400, "failure_fraction": 0.05, "success_fraction": 0.0}
set-cookie: WMF-Last-Access=31-Jan-2023;Path=/;HttpOnly;secure;Expires=Sat, 04 Mar 2023 12:00:00 GMT
set-cookie: WMF-Last-Access-Global=31-Jan-2023;Path=/;Domain=.wikipedia.org;HttpOnly;secure;Expires=Sat, 04 Mar 2023 12:00:00 GMT
accept-ch: Sec-CH-UA-Arch,Sec-CH-UA-Bitness,Sec-CH-UA-Full-Version-List,Sec-CH-UA-Model,Sec-CH-UA-Platform-Version
permissions-policy: interest-cohort=(),ch-ua-arch=(self "intake-analytics.wikimedia.org"),ch-ua-bitness=(self "intake-analytics.wikimedia.org"),ch-ua-full-version-list=(self "intake-analytics.wikimedia.org"),ch-ua-model=(self "intake-analytics.wikimedia.org"),ch-ua-platform-version=(self "intake-analytics.wikimedia.org")
x-client-ip: 2804:4ec:12dd:6500:2463:1121:5f7e:8dd2
set-cookie: GeoIP=BR:SP:Bauru:-22.26:-49.14:v4; Path=/; secure; Domain=.wikipedia.org
accept-ranges: bytes
content-length: 955889

And to request internally we need to do the following:

ssh mwmaint1002.eqiad.wmnet
curl  -sSL -D - https://mobileapps.discovery.wmnet:4102/en.wikipedia.org/v1/page/mobile-html/Barack_Obama -o /dev/null

Output:

access-control-allow-origin: *
access-control-allow-headers: accept, x-requested-with, content-type
access-control-expose-headers: etag
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
content-security-policy: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
x-content-security-policy: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
x-webkit-csp: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
content-type: text/html; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/Mobile-HTML/1.2.2"
etag: "1136227531/12116000-a169-11ed-87c2-9c08721c320e"
content-language: en
content-length: 955889
vary: Accept-Encoding
date: Tue, 31 Jan 2023 13:13:36 GMT
x-envoy-upstream-service-time: 1926
server: production-tls

Now let's request with the header to enable security headers present in the restbase response:

curl -H "x-restbase-compat: true"  -sSL -D - https://mobileapps.discovery.wmnet:4102/en.wikipedia.org/v1/page/mobile-html/Barack_Obama -o /dev/null

Output:

HTTP/1.1 200
content-language: en
content-type: text/html; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/Mobile-HTML/1.2.2"
vary: Accept-Encoding
access-control-allow-origin: *
access-control-allow-methods: GET,HEAD
access-control-allow-headers: accept, content-type, content-length, cache-control, accept-language, api-user-agent, if-match, if-modified-since, if-none-match, dnt, accept-encoding
access-control-expose-headers: etag
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
referrer-policy: origin-when-cross-origin
x-xss-protection: 1; mode=block
content-security-policy: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
x-content-security-policy: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
x-webkit-csp: default-src 'none'; connect-src app://*.wikipedia.org https://*.wikipedia.org; media-src app://upload.wikimedia.org https://upload.wikimedia.org 'self'; img-src app://*.wikimedia.org https://*.wikimedia.org app://wikimedia.org https://wikimedia.org 'self' data:; object-src 'none'; script-src app://meta.wikimedia.org https://meta.wikimedia.org 'unsafe-inline'; style-src app://meta.wikimedia.org https://meta.wikimedia.org app://*.wikipedia.org https://*.wikipedia.org 'self' 'unsafe-inline'; frame-ancestors 'self'
server: production-tls
date: Tue, 31 Jan 2023 13:17:02 GMT
etag: "1136227531/8cd4d5b0-a169-11ed-9cb3-900daf9bb992"
x-envoy-upstream-service-time: 2086
content-length: 955889