Check request origin before sending credentials (#4729)
Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com> Co-authored-by: Paul Melnikow <github@paulmelnikow.com> Co-authored-by: chris48s <chris48s@users.noreply.github.com> Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com> Co-authored-by: Paul Melnikow <github@paulmelnikow.com> Co-authored-by: chris48s <chris48s@users.noreply.github.com>
This commit is contained in:
@@ -5,9 +5,10 @@
|
||||
|
||||
const path = require('path')
|
||||
const url = require('url')
|
||||
const { URL } = url
|
||||
const bytes = require('bytes')
|
||||
const Joi = require('@hapi/joi')
|
||||
const Camp = require('camp')
|
||||
const originalJoi = require('@hapi/joi')
|
||||
const makeBadge = require('../../gh-badges/lib/make-badge')
|
||||
const GithubConstellation = require('../../services/github/github-constellation')
|
||||
const suggest = require('../../services/suggest')
|
||||
@@ -23,8 +24,44 @@ const log = require('./log')
|
||||
const sysMonitor = require('./monitor')
|
||||
const PrometheusMetrics = require('./prometheus-metrics')
|
||||
|
||||
const Joi = originalJoi
|
||||
.extend(base => ({
|
||||
type: 'arrayFromString',
|
||||
base: base.array(),
|
||||
coerce: (value, state, options) => ({
|
||||
value: typeof value === 'string' ? value.split(' ') : value,
|
||||
}),
|
||||
}))
|
||||
.extend(base => ({
|
||||
type: 'string',
|
||||
base: base.string(),
|
||||
messages: {
|
||||
'string.origin':
|
||||
'needs to be an origin string, e.g. https://host.domain with optional port and no trailing slash',
|
||||
},
|
||||
rules: {
|
||||
origin: {
|
||||
validate(value, helpers) {
|
||||
let origin
|
||||
try {
|
||||
;({ origin } = new URL(value))
|
||||
} catch (e) {}
|
||||
if (origin !== undefined && origin === value) {
|
||||
return value
|
||||
} else {
|
||||
return helpers.error('string.origin')
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
const optionalUrl = Joi.string().uri({ scheme: ['http', 'https'] })
|
||||
const requiredUrl = optionalUrl.required()
|
||||
const origins = Joi.arrayFromString().items(Joi.string().origin())
|
||||
const defaultService = Joi.object({ authorizedOrigins: origins }).default({
|
||||
authorizedOrigins: [],
|
||||
})
|
||||
|
||||
const publicConfigSchema = Joi.object({
|
||||
bind: {
|
||||
@@ -61,7 +98,9 @@ const publicConfigSchema = Joi.object({
|
||||
persistence: {
|
||||
dir: Joi.string().required(),
|
||||
},
|
||||
services: {
|
||||
services: Joi.object({
|
||||
bitbucketServer: defaultService,
|
||||
drone: defaultService,
|
||||
github: {
|
||||
baseUri: requiredUrl,
|
||||
debug: {
|
||||
@@ -72,8 +111,18 @@ const publicConfigSchema = Joi.object({
|
||||
.required(),
|
||||
},
|
||||
},
|
||||
jira: defaultService,
|
||||
jenkins: Joi.object({
|
||||
authorizedOrigins: origins,
|
||||
requireStrictSsl: Joi.boolean(),
|
||||
requireStrictSslToAuthenticate: Joi.boolean(),
|
||||
}).default({ authorizedOrigins: [] }),
|
||||
nexus: defaultService,
|
||||
npm: defaultService,
|
||||
sonar: defaultService,
|
||||
teamcity: defaultService,
|
||||
trace: Joi.boolean().required(),
|
||||
},
|
||||
}).required(),
|
||||
profiling: {
|
||||
makeBadge: Joi.boolean().required(),
|
||||
},
|
||||
@@ -296,6 +345,7 @@ class Server {
|
||||
fetchLimitBytes: bytes(config.public.fetchLimit),
|
||||
rasterUrl: config.public.rasterUrl,
|
||||
private: config.private,
|
||||
public: config.public,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -65,7 +65,7 @@ describe('The server', function() {
|
||||
|
||||
it('should produce json badges', async function() {
|
||||
const { statusCode, body, headers } = await got(
|
||||
`${baseUrl}npm/v/express.json`
|
||||
`${baseUrl}twitter/follow/_Pyves.json`
|
||||
)
|
||||
expect(statusCode).to.equal(200)
|
||||
expect(headers['content-type']).to.equal('application/json')
|
||||
|
||||
Reference in New Issue
Block a user