@remix-run/cop-middleware 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,8 +18,8 @@ npm i remix
18
18
  ## Usage
19
19
 
20
20
  ```ts
21
- import { createRouter } from 'remix/fetch-router'
22
- import { cop } from 'remix/cop-middleware'
21
+ import { createRouter } from 'remix/router'
22
+ import { cop } from 'remix/middleware/cop'
23
23
 
24
24
  let router = createRouter({
25
25
  middleware: [cop()],
@@ -51,11 +51,11 @@ You can also layer `cop()` in front of `csrf()` when you want both browser prove
51
51
 
52
52
  ```ts
53
53
  import { createCookie } from 'remix/cookie'
54
- import { createRouter } from 'remix/fetch-router'
55
- import { createCookieSessionStorage } from 'remix/session/cookie-storage'
56
- import { session } from 'remix/session-middleware'
57
- import { cop } from 'remix/cop-middleware'
58
- import { csrf } from 'remix/csrf-middleware'
54
+ import { createRouter } from 'remix/router'
55
+ import { createCookieSessionStorage } from 'remix/session-storage/cookie'
56
+ import { session } from 'remix/middleware/session'
57
+ import { cop } from 'remix/middleware/cop'
58
+ import { csrf } from 'remix/middleware/csrf'
59
59
 
60
60
  let sessionCookie = createCookie('__session', { secrets: ['secret1'] })
61
61
  let sessionStorage = createCookieSessionStorage()
@@ -70,8 +70,8 @@ In this setup, `cop()` runs first and rejects unsafe cross-origin browser reques
70
70
  ## Trusted Origins
71
71
 
72
72
  ```ts
73
- import { createRouter } from 'remix/fetch-router'
74
- import { cop } from 'remix/cop-middleware'
73
+ import { createRouter } from 'remix/router'
74
+ import { cop } from 'remix/middleware/cop'
75
75
 
76
76
  let router = createRouter({
77
77
  middleware: [
@@ -95,8 +95,8 @@ Bypass patterns intentionally weaken protection for specific endpoints. They sup
95
95
  - Tail wildcards with `{name...}`
96
96
 
97
97
  ```ts
98
- import { createRouter } from 'remix/fetch-router'
99
- import { cop } from 'remix/cop-middleware'
98
+ import { createRouter } from 'remix/router'
99
+ import { cop } from 'remix/middleware/cop'
100
100
 
101
101
  let router = createRouter({
102
102
  middleware: [
@@ -1 +1 @@
1
- {"version":3,"file":"cop.d.ts","sourceRoot":"","sources":["../../src/lib/cop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAiB,MAAM,yBAAyB,CAAA;AAaxF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,GAAG,uCAAuC,CAAA;AAE/F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAClF;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAElC;;OAEG;IACH,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAE1C;;OAEG;IACH,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAqFD;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,OAAO,GAAE,UAAe,GAAG,UAAU,CAWxD"}
1
+ {"version":3,"file":"cop.d.ts","sourceRoot":"","sources":["../../src/lib/cop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAiB,MAAM,yBAAyB,CAAA;AAaxF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,sBAAsB,GAAG,uCAAuC,CAAA;AAE/F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CAClF;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAElC;;OAEG;IACH,sBAAsB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAE1C;;OAEG;IACH,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAyFD;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,OAAO,GAAE,UAAe,GAAG,UAAU,CAWxD"}
package/dist/lib/cop.js CHANGED
@@ -1,4 +1,4 @@
1
- import { RequestMethods } from '@remix-run/fetch-router';
1
+ import { isRequestMethod } from '@remix-run/fetch-router';
2
2
  const safeMethods = ['GET', 'HEAD', 'OPTIONS'];
3
3
  class CrossOriginProtection {
4
4
  #trustedOrigins = new Set();
@@ -23,7 +23,7 @@ class CrossOriginProtection {
23
23
  this.#onDeny = onDeny;
24
24
  }
25
25
  check(context) {
26
- if (safeMethods.includes(context.method)) {
26
+ if (isSafeMethod(context.method)) {
27
27
  return null;
28
28
  }
29
29
  let secFetchSite = getHeaderValue(context.headers, 'Sec-Fetch-Site')?.toLowerCase() ?? '';
@@ -66,6 +66,9 @@ class CrossOriginProtection {
66
66
  return normalizedOrigin != null && this.#trustedOrigins.has(normalizedOrigin);
67
67
  }
68
68
  }
69
+ function isSafeMethod(method) {
70
+ return isRequestMethod(method) && safeMethods.includes(method);
71
+ }
69
72
  /**
70
73
  * Creates middleware that rejects unsafe cross-origin requests.
71
74
  *
@@ -145,7 +148,7 @@ function parseBypassPattern(pattern) {
145
148
  let methodPattern = /^([A-Z]+)\s+(.+)$/.exec(trimmedPattern);
146
149
  if (methodPattern != null && methodPattern[2].startsWith('/')) {
147
150
  let maybeMethod = methodPattern[1];
148
- if (!RequestMethods.includes(maybeMethod)) {
151
+ if (!isRequestMethod(maybeMethod)) {
149
152
  throw new Error(`invalid request method in bypass pattern ${JSON.stringify(pattern)}`);
150
153
  }
151
154
  method = maybeMethod;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remix-run/cop-middleware",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Middleware for tokenless cross-origin protection in Fetch API servers",
5
5
  "author": "Michael Jackson <mjijackson@gmail.com>",
6
6
  "license": "MIT",
@@ -28,12 +28,12 @@
28
28
  "devDependencies": {
29
29
  "@types/node": "^24.6.0",
30
30
  "@typescript/native-preview": "7.0.0-dev.20251125.1",
31
- "@remix-run/fetch-router": "0.18.1",
32
- "@remix-run/assert": "0.1.0",
33
- "@remix-run/test": "0.1.0"
31
+ "@remix-run/fetch-router": "0.19.0",
32
+ "@remix-run/assert": "0.2.0",
33
+ "@remix-run/test": "0.4.0"
34
34
  },
35
35
  "dependencies": {
36
- "@remix-run/fetch-router": "^0.18.1"
36
+ "@remix-run/fetch-router": "^0.19.0"
37
37
  },
38
38
  "keywords": [
39
39
  "fetch",
@@ -47,6 +47,7 @@
47
47
  "build": "tsgo -p tsconfig.build.json",
48
48
  "clean": "git clean -fdX",
49
49
  "test": "remix-test",
50
+ "test:bun": "bun x --bun remix-test",
50
51
  "typecheck": "tsgo --noEmit"
51
52
  }
52
53
  }
package/src/lib/cop.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { RequestMethods } from '@remix-run/fetch-router'
1
+ import { isRequestMethod } from '@remix-run/fetch-router'
2
2
  import type { Middleware, RequestContext, RequestMethod } from '@remix-run/fetch-router'
3
3
 
4
4
  const safeMethods: RequestMethod[] = ['GET', 'HEAD', 'OPTIONS']
@@ -77,7 +77,7 @@ class CrossOriginProtection {
77
77
  }
78
78
 
79
79
  check(context: RequestContext): CopFailureReason | null {
80
- if (safeMethods.includes(context.method)) {
80
+ if (isSafeMethod(context.method)) {
81
81
  return null
82
82
  }
83
83
 
@@ -130,6 +130,10 @@ class CrossOriginProtection {
130
130
  }
131
131
  }
132
132
 
133
+ function isSafeMethod(method: string): boolean {
134
+ return isRequestMethod(method) && safeMethods.includes(method)
135
+ }
136
+
133
137
  /**
134
138
  * Creates middleware that rejects unsafe cross-origin requests.
135
139
  *
@@ -228,8 +232,8 @@ function parseBypassPattern(pattern: string): BypassPattern {
228
232
  let methodPattern = /^([A-Z]+)\s+(.+)$/.exec(trimmedPattern)
229
233
 
230
234
  if (methodPattern != null && methodPattern[2].startsWith('/')) {
231
- let maybeMethod = methodPattern[1] as RequestMethod
232
- if (!RequestMethods.includes(maybeMethod)) {
235
+ let maybeMethod = methodPattern[1]
236
+ if (!isRequestMethod(maybeMethod)) {
233
237
  throw new Error(`invalid request method in bypass pattern ${JSON.stringify(pattern)}`)
234
238
  }
235
239