Skip to content

Commit

Permalink
fix(ui): CSP (#913)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Justin Law <justin.law@defenseunicorns.com>
  • Loading branch information
andrewrisse and justinthelaw committed Aug 16, 2024
1 parent 0ff7aa7 commit b83ef04
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/leapfrogai_api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dependencies = [
"python-multipart >= 0.0.7", #indirect dep of FastAPI to receive form data for file uploads
"watchfiles >= 0.21.0",
"leapfrogai_sdk",
"supabase >= 2.5.1",
"supabase == 2.6.0",
"langchain >= 0.2.1",
"langchain-community >= 0.2.1",
"unstructured[md,xlsx,pptx] >= 0.15.3", # Only specify necessary filetypes to prevent package bloat (e.g. 130MB vs 6GB)
Expand Down
2 changes: 1 addition & 1 deletion src/leapfrogai_ui/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LEAPFROGAI_API_BASE_URL=https://leapfrogai-api.uds.dev #for OpenAI it would be:
SUPABASE_AUTH_EXTERNAL_KEYCLOAK_URL=https://sso.uds.dev/realms/uds
SUPABASE_AUTH_KEYCLOAK_CLIENT_ID=uds-supabase
SUPABASE_AUTH_KEYCLOAK_SECRET=<secret>
ORIGIN=http://localhost:5137
#ORIGIN=http://localhost:3000 # set if running in Docker locally (variable is also used in deployment)

#If specified, app will use OpenAI instead of Leapfrog
OPENAI_API_KEY=
Expand Down
33 changes: 32 additions & 1 deletion src/leapfrogai_ui/src/hooks.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,35 @@ const authGuard: Handle = async ({ event, resolve }) => {
return resolve(event);
};

export const handle: Handle = sequence(supabase, authGuard);
const csp: Handle = async ({ event, resolve }) => {
const response = await resolve(event);
const directives = {
'default-src': ["'none'"],
'base-uri': ["'self'"],
'object-src': ["'none'"], // typically used for legacy content, such as Flash files or Java applets
'style-src': ["'self'", "'unsafe-inline'"],
'font-src': ["'self'"],
'manifest-src': ["'self'"],
'img-src': ["'self'", `data: 'self' ${process.env.PUBLIC_SUPABASE_URL}`, `blob: 'self'`],
'media-src': ["'self'"],
'form-action': ["'self'"],
'connect-src': [
"'self'",
process.env.LEAPFROGAI_API_BASE_URL,
process.env.PUBLIC_SUPABASE_URL,
process.env.SUPABASE_AUTH_EXTERNAL_KEYCLOAK_URL
],
'child-src': ["'none'"], // note - this will break the annotations story and will need to updated to allow the correct resource
'frame-ancestors': ["'none'"]
};

const CSP = Object.entries(directives)
.map(([key, arr]) => key + ' ' + arr.join(' '))
.join('; ');
// We use Sveltekits generated CSP for script-src to get the nonce
const svelteKitGeneratedCSPWithNonce = response.headers.get('Content-Security-Policy');
response.headers.set('Content-Security-Policy', `${CSP}; ${svelteKitGeneratedCSPWithNonce}`);
return response;
};

export const handle: Handle = sequence(csp, supabase, authGuard);
25 changes: 3 additions & 22 deletions src/leapfrogai_ui/svelte.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,10 @@ const config = {
$testUtils: 'testUtils'
},
csp: {
// Remainder of the CSP is set in hooks.server.ts, we partially define here for the nonce generation provided
// by Sveltekit
directives: {
'default-src': ['none'],
'base-uri': ['self'],
'script-src': ['self', 'strict-dynamic'],
'object-src': ['none'], // typically used for legacy content, such as Flash files or Java applets
'style-src': ['self', 'unsafe-inline'],
'font-src': ['self'],
'manifest-src': ['self'],
'img-src': [
'self',
`data: ${process.env.ORIGIN} ${process.env.PUBLIC_SUPABASE_URL}`,
`blob: ${process.env.ORIGIN}`
],
'media-src': ['self'],
'form-action': ['self'],
'connect-src': [
'self',
process.env.LEAPFROGAI_API_BASE_URL || '',
process.env.PUBLIC_SUPABASE_URL || '',
process.env.SUPABASE_AUTH_EXTERNAL_KEYCLOAK_URL || ''
],
'child-src': [`blob: ${process.env.ORIGIN}`],
'frame-ancestors': ['none']
'script-src': ['self', 'strict-dynamic']
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/leapfrogai_ui/tests/global.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { delay } from 'msw';
const authFile = 'playwright/.auth/user.json';

setup('authenticate', async ({ page }) => {
page.on('pageerror', (err) => {
console.log(err.message);
});

await page.goto('/'); // go to the home page
await delay(2000); // allow page to fully hydrate
if (process.env.PUBLIC_DISABLE_KEYCLOAK === 'true') {
Expand Down

0 comments on commit b83ef04

Please sign in to comment.