Skip to content

Commit

Permalink
Merge pull request #8 from IslamZaoui/dev
Browse files Browse the repository at this point in the history
merge dev into main
  • Loading branch information
IslamZaoui authored Sep 29, 2024
2 parents 8148c57 + 7e4bad5 commit 7027305
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 4,511 deletions.
23 changes: 10 additions & 13 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI
name: CI/CD

on:
push:
Expand All @@ -13,19 +13,16 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up pnpm
uses: pnpm/action-setup@v4
- name: Set up bun
uses: oven-sh/setup-bun@v2
with:
version: 9.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'pnpm'
bun-version: 1.1.29

- name: Install dependencies
run: pnpm install --frozen-lockfile
run: bun install --frozen-lockfile

- name: Run lint
run: bun lint

- name: Run linter
run: pnpm lint && pnpm build
- name: Run build
run: bun run build
18 changes: 6 additions & 12 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Publish
on:
workflow_run:
workflows: [Lint]
workflows: [CI/CD]
branches: [main]
types: [completed]

Expand All @@ -19,25 +19,19 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Set up bun
uses: oven-sh/setup-bun@v2
with:
version: 9.11.0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'pnpm'
bun-version: 1.1.29

- name: Install Dependencies
run: pnpm install --frozen-lockfile
run: bun install --frozen-lockfile

- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
with:
publish: pnpm run release
publish: bun release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
node_modules
dist
.vercel
.vercel
bun.lockb
.turbo
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

Secure your [sveltekit](https://kit.svelte.dev/) app using [http response headers](https://cheatsheetseries.owasp.org/cheatsheets/HTTP_Headers_Cheat_Sheet.html)

[![Lint](https://github.com/IslamZaoui/securekit/actions/workflows/lint.yaml/badge.svg)](https://github.com/IslamZaoui/securekit/actions/workflows/lint.yaml)
[![npm](https://img.shields.io/npm/v/%40islamzaoui%2Fsecurekit)](https://www.npmjs.com/package/@islamzaoui/securekit)
[![CI/CD](https://github.com/IslamZaoui/securekit/actions/workflows/lint.yaml/badge.svg)](https://github.com/IslamZaoui/securekit/actions/workflows/lint.yaml)
[![NPM](https://img.shields.io/npm/v/%40islamzaoui%2Fsecurekit)](https://www.npmjs.com/package/@islamzaoui/securekit)
[![Issues](https://img.shields.io/github/issues/IslamZaoui/securekit)](https://github.com/IslamZaoui/securekit/issues)
[![License](https://img.shields.io/github/license/IslamZaoui/securekit)](https://github.com/IslamZaoui/securekit/blob/main/LICENSE)

Expand All @@ -19,6 +19,8 @@ you can also use other package managers like [pnpm](https://pnpm.io/) or [yarn](

### default headers

this will add the default headers to the response, this will be enough to get your website A grade in [security headers](https://securityheaders.com/)

```ts
// src/hooks.server.ts
import { securityHeaders } from '@islamzaoui/securekit';
Expand All @@ -28,6 +30,8 @@ export const handle = securityHeaders().handle;

### with custom headers

you can customize the headers you want to set, and override any of the headers available in response headers.

```ts
// src/hooks.server.ts
import { securityHeaders } from '@islamzaoui/securekit';
Expand All @@ -46,6 +50,8 @@ export const handle = securityHeaders({

### with multiple handles

you can use [sequence](https://kit.svelte.dev/docs/modules#sveltejs-kit-hooks) to sequencing other handles with `securityHeaders`.

```ts
// src/hooks.server.ts
import { securityHeaders } from '@islamzaoui/securekit';
Expand All @@ -61,10 +67,32 @@ export const handle = sequence(
);
```

### delete headers

set the value to `null` to delete the header.

```ts
// src/hooks.server.ts
import { securityHeaders } from '@islamzaoui/securekit';

export const handle = securityHeaders({
headers: {
'Access-Control-Allow-Origin': 'https://yoursite.com',
'x-sveltekit-page': null, // this will be deleted
},
});
```

## Content Security Policy header

your can use `csp` option in `securityHeaders` to set the `Content-Security-Policy` header directives.

**Note**:

- `config.csp` directives will override any existing directives in the `Content-Security-Policy` header.

- `config.csp` directives will extend the existing directives in [svelte.config.js](https://kit.svelte.dev/docs/configuration#csp)

```ts
// src/hooks.server.ts
import { securityHeaders } from '@islamzaoui/securekit';
Expand Down
9 changes: 4 additions & 5 deletions apps/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,25 @@
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write .",
"postinstall": "cd ../../packages/securekit && pnpm run build"
"format": "prettier --write ."
},
"devDependencies": {
"@sveltejs/adapter-vercel": "^5.4.4",
"@sveltejs/kit": "catalog:default",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@types/eslint": "^9.6.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.36.0",
"globals": "^15.0.0",
"prettier": "catalog:default",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.6.5",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
"tailwindcss": "^3.4.9",
"typescript": "catalog:default",
"typescript": "^5.0.0",
"typescript-eslint": "^8.0.0",
"vite": "^5.0.3"
},
Expand Down
9 changes: 5 additions & 4 deletions apps/demo/src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { dev } from '$app/environment';
import { rules, securityHeaders } from '@islamzaoui/securekit';
import { securityHeaders, rules } from '@islamzaoui/securekit';

const origin = dev ? 'http://localhost:5173' : 'https://securekit-demo.vercel.app';

export const handle = securityHeaders({
headers: {
...rules.defaultHeaders,
'Access-Control-Allow-Origin': origin
'Access-Control-Allow-Origin': origin,
'x-sveltekit-page': null
},
csp: {
directives: {
Expand All @@ -21,9 +22,9 @@ export const handle = securityHeaders({
'manifest-src': ["'self'"],
'media-src': ["'self'", 'data:'],
'object-src': ["'none'"],
'style-src': ["'self'", "'unsafe-inline'"],
'style-src': ["'self'"],
'default-src': ["'self'", origin],
'script-src': ["'self'", "'unsafe-inline'"],
'script-src': ["'self'"],
'worker-src': ["'self'"]
}
},
Expand Down
8 changes: 7 additions & 1 deletion apps/demo/svelte.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ const config = {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter()
adapter: adapter(),
csp: {
mode: 'auto',
directives: {
'default-src': ["'self'"]
}
}
}
};

Expand Down
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
"name": "monorepo",
"private": true,
"scripts": {
"build": "pnpm run -r build",
"dev": "pnpm run -r --parallel --stream dev",
"release": "pnpm run -r build && changeset publish",
"lint": "prettier --check \"**/*.{json,md}\" && pnpm run -r lint",
"format": "prettier --write \"**/*.{json,md}\" && pnpm run -r format"
"build": "turbo run build",
"dev": "turbo run dev",
"release": "turbo run build && changeset publish",
"lint": "prettier --check \"**/*.{json,md}\" && turbo run lint",
"format": "prettier --write \"**/*.{json,md}\" && turbo run format"
},
"workspaces": [
"packages/*",
"apps/*"
],
"devDependencies": {
"@changesets/cli": "catalog:default",
"prettier": "catalog:default"
"@changesets/cli": "^2.27.8",
"prettier": "^3.1.1",
"turbo": "^2.1.2"
},
"packageManager": "[email protected]"
"packageManager": "[email protected]"
}
8 changes: 4 additions & 4 deletions packages/securekit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
"license": "MIT",
"description": "Secure your sveltekit app using http response security headers",
"devDependencies": {
"prettier": "catalog:default",
"tsup": "catalog:default",
"typescript": "catalog:default"
"prettier": "^3.1.1",
"tsup": "^8.3.0",
"typescript": "^5.0.0"
},
"peerDependencies": {
"@sveltejs/kit": "catalog:default"
"@sveltejs/kit": "^2.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HTTPResponseHeaders } from './types/http';
import { HTTPResponseHeaders } from '../types/http';

const defaultHeaders: HTTPResponseHeaders = {
'X-Frame-Options': 'DENY',
Expand All @@ -7,7 +7,7 @@ const defaultHeaders: HTTPResponseHeaders = {
'Permissions-Policy': 'geolocation=(), camera=(), microphone=()',
};

export const rules = {
export default {
/**
* Default headers for secure headers.
* @example
Expand Down
62 changes: 3 additions & 59 deletions packages/securekit/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,3 @@
import { Handle } from '@sveltejs/kit';
import { Config } from './types';
import { normalizeCspValue, normalizeHeaderValue } from './utils';
import { rules } from './headers';

/**
* sets HTTP response security headers based on the provided configuration.
*
* @param {Config} [config] - Configuration object for secure headers.
* @param {Object} [config.headers] - Custom headers to set.
* @param {boolean} [config.debug] - Enables debug logging if true.
* @param {Object} [config.csp] - Content Security Policy directives.
* @returns {Object} An object containing the handle function to process requests.
*/
export const securityHeaders = (
config: Config = {
headers: {
...rules.defaultHeaders,
},
debug: false,
csp: undefined,
},
) => {
const headers = new Map<string, string>();

if (config?.headers) {
Object.entries(config.headers).forEach(([key, value]) => {
value && headers.set(key, normalizeHeaderValue(value));
});
}

if (config?.csp) {
const cspDirectives = Object.entries(config.csp.directives)
.map(([key, value]) => `${key} ${normalizeCspValue(value)}`)
.join('; ');
headers.set('Content-Security-Policy', cspDirectives);
}

const handle: Handle = async ({ event, resolve }) => {
if (config?.debug) {
console.log(
'[DEBUG] securekit Headers:',
JSON.stringify(Object.fromEntries(headers), null, 2),
);
}

const response = await resolve(event);

headers.forEach((value, key) => {
response.headers.set(key, value);
});

return response;
};

return { handle };
};

export { rules } from './headers';
export { securityHeaders } from './securityHeaders';
export { default as rules } from './constants/rules';
export * from './types';
Loading

0 comments on commit 7027305

Please sign in to comment.