Merge pull request #2495 from caprover/fix/deploy-token-authorization

fix: return unauthorized for invalid app deploy tokens
This commit is contained in:
Kasra Bigdeli authored and GitHub committed 2026-09-21 19:01:34 -07:00
commit cb12183a18
2 files changed
+59 -1

No files matched your search

+6 -1
View File
@@ -145,7 +145,12 @@ export function injectUserForBuildTrigger() {
if (!tokenMatches) {
Logger.e('Token mismatch for app build')
next()
res.send(
new BaseApi(
ApiStatusCodes.STATUS_ERROR_NOT_AUTHORIZED,
'The request is not authorized.'
)
)
return
}
+53
View File
@@ -0,0 +1,53 @@
jest.mock('../src/docker/DockerApi', () => ({
__esModule: true,
default: { get: jest.fn(() => ({})) },
}))
jest.mock('../src/datastore/DataStoreProvider', () => ({
__esModule: true,
default: { getDataStore: jest.fn() },
}))
import DataStoreProvider from '../src/datastore/DataStoreProvider'
import { injectUserForBuildTrigger } from '../src/injection/Injector'
describe('build trigger token injection', () => {
it('returns not authorized for a mismatched app deploy token', async () => {
const getAppDefinition = jest.fn().mockResolvedValue({
appDeployTokenConfig: {
enabled: true,
appDeployToken: 'expected-token',
},
})
;(DataStoreProvider.getDataStore as jest.Mock).mockReturnValue({
getAppsDataStore: () => ({ getAppDefinition }),
})
let resolveResponse: () => void = () => undefined
const responseSent = new Promise<void>((resolve) => {
resolveResponse = resolve
})
const response = {
locals: { namespace: 'captain' },
send: jest.fn(() => resolveResponse()),
}
const request = {
header: jest.fn((name: string) =>
name === 'x-captain-app-token' ? 'invalid-token' : undefined
),
params: { appName: 'test-app' },
}
const next = jest.fn()
injectUserForBuildTrigger()(request as any, response as any, next)
await responseSent
expect(response.send).toHaveBeenCalledWith(
expect.objectContaining({
status: 1102,
description: 'The request is not authorized.',
})
)
expect(next).not.toHaveBeenCalled()
})
})