Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: security headers for apps #65

Merged
merged 24 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6138d54
feat: Add next-middleware library and related files
mohandast52 Jul 17, 2024
fffbd6c
feat: renames files for middleware
mohandast52 Jul 17, 2024
9c2cc7d
feat: remove unsafe-inline for style-src
mohandast52 Jul 17, 2024
110a1fc
chore: include object-src
mohandast52 Jul 18, 2024
4e9e5f0
chore: remove unsafe inline for firefox
mohandast52 Jul 18, 2024
1f3b301
chore: IMPORTANT - got A+ but changing the policy to make it work as …
mohandast52 Jul 18, 2024
833af20
chore: adding unsafe-inline for style-src
mohandast52 Jul 18, 2024
7c2e733
chore: remove font-src, object-src and scriptSrc to have unsafe-inlin…
mohandast52 Jul 18, 2024
21c6679
refractor: move constants above the function in cspHeader, remove bro…
mohandast52 Jul 18, 2024
3141d5b
chore: add 'nonce' support for style-src and commented unsafe-inline
mohandast52 Jul 18, 2024
19c4169
chore: add nonce
mohandast52 Jul 18, 2024
8255b0e
chore: remove nonce and add unsafe-inline for style
mohandast52 Jul 18, 2024
239bd74
chore: add api.thegraph.com origin
mohandast52 Jul 18, 2024
9fe74ed
feat: add middleware to other apps
mohandast52 Jul 18, 2024
5eefbe5
feat: remove headers from next.config.js for bond & tokenomics app
mohandast52 Jul 18, 2024
765c606
chore: rename getCspHeader function name
mohandast52 Jul 18, 2024
3f79d9a
Update libs/common-middleware/src/lib/cspHeader.ts
mohandast52 Jul 19, 2024
5978445
refactor: Remove duplicate code for address prohibition check
mohandast52 Jul 19, 2024
e34c720
Merge branch 'mohan/security-header' of github.com-personal:valory-xy…
mohandast52 Jul 19, 2024
44f7b3c
refactor: Remove duplicate code for address prohibition check
mohandast52 Jul 19, 2024
4c0d5eb
fix: conflict merge
mohandast52 Jul 22, 2024
9f4d6b7
feat: Add Vercel links to CSP allowed origins
mohandast52 Jul 24, 2024
2aa4f89
feat: Add gateway links to CSP allowed origins
mohandast52 Jul 24, 2024
174e78a
feat: Update IPFS gateway links in CSP allowed origins
mohandast52 Jul 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 3 additions & 149 deletions apps/autonolas-registry/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,150 +1,4 @@
import nextSafe from 'next-safe';
import { NextRequest, NextResponse, userAgent } from 'next/server';
import { config, middleware } from 'libs/common-middleware/src';

import prohibitedCountries from 'libs/util-prohibited-data/src/lib/prohibited-countries.json';

const prohibitedCountriesCode = Object.values(prohibitedCountries);

const isDev = process.env.NODE_ENV !== 'production';

const getCspHeader = (browserName?: string) => {
if (!process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL) return [];

const walletconnectSrc = ['https://verify.walletconnect.org', 'https://verify.walletconnect.com'];

const connectSrc: CSPDirective = [
"'self'",
...walletconnectSrc,
'https://*.olas.network/',
'https://*.autonolas.tech/',
'https://rpc.walletconnect.com/',
'wss://relay.walletconnect.org/',
'wss://relay.walletconnect.com/',
'https://explorer-api.walletconnect.com/',
'https://eth-mainnet.g.alchemy.com/v2/',
'https://eth-goerli.g.alchemy.com/v2/',
'https://gno.getblock.io/',
'https://polygon-mainnet.g.alchemy.com/v2/',
'https://polygon-mumbai-bor.publicnode.com/',
'https://rpc.chiado.gnosis.gateway.fm/',
'https://safe-transaction-mainnet.safe.global/api/v1/',
'https://safe-transaction-goerli.safe.global/api/',
'https://safe-transaction-gnosis-chain.safe.global/api/',
'https://safe-transaction-polygon.safe.global/api/',
'https://vercel.live/',
'https://api.devnet.solana.com/',
'wss://api.devnet.solana.com/',
'https://api.mainnet-beta.solana.com/',
'wss://api.mainnet-beta.solana.com/',
'https://holy-convincing-bird.solana-mainnet.quiknode.pro/',
'wss://holy-convincing-bird.solana-mainnet.quiknode.pro/',
'https://arb1.arbitrum.io/rpc/',
'https://sepolia-rollup.arbitrum.io/rpc',
'https://rpc.gnosischain.com/',
'https://mainnet.base.org/',
'https://sepolia.base.org/',
'https://mainnet.optimism.io',
'https://sepolia.optimism.io/',
'https://forno.celo.org',
'https://alfajores-forno.celo-testnet.org',
'https://api.web3modal.com/',
'wss://www.walletlink.org/rpc',
'wss://*.pusher.com/',
process.env.NEXT_PUBLIC_AUTONOLAS_SUB_GRAPH_URL,
];

if (isDev) {
connectSrc.push('http://localhost');
connectSrc.push('ws://localhost');
}

const scriptSrc = ["'self'", 'https://vercel.live/', 'https://fonts.googleapis.com/'];

// Firefox blocks inline scripts by default and it's an issue with Metamask
// reference: https://github.com/MetaMask/metamask-extension/issues/3133
if (browserName === 'Firefox') {
scriptSrc.push("'unsafe-inline'");
}

const nextSafeHeaders =
typeof nextSafe === 'function'
? // TODO
// @ts-expect-error: For some reason, TypeScript is not recognizing the function
nextSafe({
isDev,
/**
* Content Security Policy
* @see https://content-security-policy.com/
*/
contentSecurityPolicy: {
'default-src': "'none'",
'script-src': scriptSrc,
'connect-src': connectSrc,
'img-src': [
"'self'",
'blob:',
'data:',
'https://*.autonolas.tech/',
'https://explorer-api.walletconnect.com/w3m/',
...walletconnectSrc,
],
'style-src': ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com/'],
'frame-src': ["'self'", 'https://vercel.live/', ...walletconnectSrc],
},
permissionsPolicyDirectiveSupport: ['standard'],
})
: [];

const headers = [
...nextSafeHeaders,
{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains',
},
];

return headers;
};

const getRedirectUrl = (pathName: string, countryName?: string) => {
const isProhibited = countryName ? prohibitedCountriesCode.includes(countryName) : false;

if (pathName === '/not-legal') {
return isProhibited ? null : '/';
}
return isProhibited ? '/not-legal' : null;
};

export default async function middleware(request: NextRequest) {
const country = request.geo?.country;
const redirectUrl = getRedirectUrl(request.nextUrl.pathname, country);

const response = redirectUrl
? NextResponse.redirect(new URL(redirectUrl, request.nextUrl))
: NextResponse.next();

const browserName = userAgent(request)?.browser.name;
const cspHeaders = getCspHeader(browserName);

// apply CSP headers
// https://nextjs.org/docs/app/building-your-application/routing/middleware#setting-headers
cspHeaders.forEach((header) => {
const { key, value } = header;
response.headers.set(key, value);
});

return response;
}

export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
'/((?!api|_next/static|_next/image|favicon.ico).*)',
],
};
export default middleware;
export { config };
4 changes: 4 additions & 0 deletions apps/bond/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { config, middleware } from 'libs/common-middleware/src';

export default middleware;
export { config };
35 changes: 0 additions & 35 deletions apps/bond/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,6 @@ const nextConfig = {
};
return config;
},
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: "frame-ancestors 'none';",
},
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
{
key: 'Referrer-Policy',
value: 'strict-origin-when-cross-origin',
},
{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains',
},
],
},
{
source: '/:all*(svg|jpg|jpeg|png|gif|ico|css|js|mov|mp4)',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, must-revalidate',
},
],
},
];
},

};

const plugins = [
Expand Down
4 changes: 4 additions & 0 deletions apps/govern/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { config, middleware } from 'libs/common-middleware/src';

export default middleware;
export { config };
4 changes: 4 additions & 0 deletions apps/launch/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { config, middleware } from 'libs/common-middleware/src';

export default middleware;
export { config };
4 changes: 4 additions & 0 deletions apps/tokenomics/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { config, middleware } from 'libs/common-middleware/src';

export default middleware;
export { config };
25 changes: 0 additions & 25 deletions apps/tokenomics/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,6 @@ const nextConfig = {
},
];
},
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: "frame-ancestors 'none';",
},
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
{
key: 'Referrer-Policy',
value: 'strict-origin-when-cross-origin',
},
{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains',
},
],
},
];
},
};
const plugins = [
// Add more Next.js plugins to this list if needed.
Expand Down
18 changes: 18 additions & 0 deletions libs/common-middleware/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
5 changes: 5 additions & 0 deletions libs/common-middleware/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# common-middleware

Common middleware for apps, including:
- Prohibition of specific countries and addresses
- Implementation of security headers
13 changes: 13 additions & 0 deletions libs/common-middleware/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "common-middleware",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/common-middleware/src",
"projectType": "library",
"tags": [],
"targets": {
"lint": {
"executor": "@nx/eslint:lint",
"outputs": ["{options.outputFile}"]
}
}
}
1 change: 1 addition & 0 deletions libs/common-middleware/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { config, middleware } from './middleware';
Loading
Loading