Skip to content

Commit 4e221d9

Browse files
committed
f
1 parent 109ce71 commit 4e221d9

File tree

51 files changed

+515
-437
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+515
-437
lines changed

__snapshots__/csp.test.ts.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@ exports['test/csp.test.ts should ignore path 1'] = {
5555
"value": "1; mode=block"
5656
},
5757
"csp": {
58-
"ignore": [
59-
"/api/",
60-
{}
61-
],
6258
"enable": true,
6359
"policy": {
6460
"script-src": [
@@ -80,7 +76,11 @@ exports['test/csp.test.ts should ignore path 1'] = {
8076
"'self'"
8177
],
8278
"report-uri": "http://pointman.domain.com/csp?app=csp"
83-
}
79+
},
80+
"ignore": [
81+
"/api/",
82+
{}
83+
]
8484
},
8585
"referrerPolicy": {
8686
"enable": false,

__snapshots__/csrf.test.ts.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
exports['test/csrf.test.ts should update form with csrf token 1'] = {
2-
"ignore": [
3-
{},
4-
null
5-
],
62
"enable": true,
73
"type": "ctoken",
84
"ignoreJSON": false,
@@ -30,7 +26,11 @@ exports['test/csrf.test.ts should update form with csrf token 1'] = {
3026
"signed": false,
3127
"httpOnly": false,
3228
"overwrite": true
33-
}
29+
},
30+
"ignore": [
31+
{},
32+
null
33+
]
3434
}
3535

3636
exports['test/csrf.test.ts apps/csrf-supported-requests-default-config should works without error because csrf = false override default config 1'] = {

__snapshots__/xss.test.ts.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
exports['test/xss.test.ts should set X-XSS-Protection header value 0 when config is number 0 1'] = {
2+
"enable": true,
3+
"value": 0
4+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"@arethetypeswrong/cli": "^0.17.1",
5454
"@eggjs/bin": "7",
5555
"@eggjs/mock": "^6.0.5",
56-
"@eggjs/supertest": "^8.1.1",
56+
"@eggjs/supertest": "^8.2.0",
5757
"@eggjs/tsconfig": "1",
5858
"@types/escape-html": "^1.0.4",
5959
"@types/extend": "^3.0.4",

src/app.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ export default class AgentBoot implements ILifecycleBoot {
1313
const app = this.app;
1414
app.config.coreMiddleware.push('securities');
1515
// parse config and check if config is legal
16-
app.config.security = SecurityConfig.parse(app.config.security);
16+
const parsed = SecurityConfig.parse(app.config.security);
17+
if (typeof app.config.security.csrf === 'boolean') {
18+
// support old config: `config.security.csrf = false`
19+
app.config.security.csrf = parsed.csrf;
20+
}
1721

1822
if (app.config.security.csrf.enable) {
1923
const { ignoreJSON } = app.config.security.csrf;

src/app/extend/agent.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
import { EggCore } from '@eggjs/core';
2-
import { safeCurlForApplication } from '../../lib/extend/safe_curl.js';
2+
import {
3+
safeCurlForApplication,
4+
type HttpClientRequestURL,
5+
type HttpClientOptions,
6+
type HttpClientResponse,
7+
} from '../../lib/extend/safe_curl.js';
38

49
export default class SecurityAgent extends EggCore {
5-
safeCurl = safeCurlForApplication;
10+
async safeCurl<T = any>(
11+
url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>> {
12+
return await safeCurlForApplication<T>(this, url, options);
13+
}
614
}

src/app/extend/application.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { EggCore } from '@eggjs/core';
2-
import { safeCurlForApplication } from '../../lib/extend/safe_curl.js';
2+
import {
3+
safeCurlForApplication,
4+
type HttpClientRequestURL,
5+
type HttpClientOptions,
6+
type HttpClientResponse,
7+
} from '../../lib/extend/safe_curl.js';
38

49
const INPUT_CSRF = '\r\n<input type="hidden" name="_csrf" value="{{ctx.csrf}}" /></form>';
510
const INJECTION_DEFENSE = '<!--for injection--><!--</html>--><!--for injection-->';
@@ -30,14 +35,17 @@ export default class SecurityApplication extends EggCore {
3035
return INJECTION_DEFENSE + html + INJECTION_DEFENSE;
3136
}
3237

33-
safeCurl = safeCurlForApplication;
38+
async safeCurl<T = any>(
39+
url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>> {
40+
return await safeCurlForApplication<T>(this, url, options);
41+
}
3442
}
3543

3644
declare module '@eggjs/core' {
3745
interface EggCore {
3846
injectCsrf(html: string): string;
3947
injectNonce(html: string): string;
4048
injectHijackingDefense(html: string): string;
41-
safeCurl: typeof safeCurlForApplication;
49+
safeCurl<T = any>(url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>>;
4250
}
4351
}

src/app/extend/context.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as utils from '../../lib/utils.js';
66
import type {
77
HttpClientRequestURL,
88
HttpClientOptions,
9-
HttpClientRequestReturn,
9+
HttpClientResponse,
1010
} from '../../lib/extend/safe_curl.js';
1111
import { SecurityConfig, SecurityHelperConfig } from '../../types.js';
1212

@@ -258,8 +258,13 @@ export default class SecurityContext extends Context {
258258
}
259259
}
260260

261-
async safeCurl(url: HttpClientRequestURL, options?: HttpClientOptions): HttpClientRequestReturn {
262-
return await this.app.safeCurl(url, options);
261+
async safeCurl<T = any>(
262+
url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>> {
263+
return await this.app.safeCurl<T>(url, options);
264+
}
265+
266+
unsafeRedirect(url: string, alt?: string) {
267+
this.response.unsafeRedirect(url, alt);
263268
}
264269
}
265270

@@ -272,6 +277,6 @@ declare module '@eggjs/core' {
272277
ensureCsrfSecret(rotate?: boolean): void;
273278
rotateCsrfSecret(): void;
274279
assertCsrf(): void;
275-
safeCurl(url: HttpClientRequestURL, options?: HttpClientOptions): HttpClientRequestReturn;
280+
safeCurl<T = any>(url: HttpClientRequestURL, options?: HttpClientOptions): Promise<HttpClientResponse<T>>;
276281
}
277282
}

src/app/extend/response.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ export default class SecurityResponse extends KoaResponse {
2020
* ctx.unsafeRedirect('http://www.domain.com');
2121
* ```
2222
*/
23-
unsafeRedirect = unsafeRedirect;
23+
unsafeRedirect(url: string, alt?: string) {
24+
unsafeRedirect.call(this, url, alt);
25+
}
2426

2527
// app.response.unsafeRedirect = app.response.redirect;
2628
// delegate(app.context, 'response').method('unsafeRedirect');
@@ -48,7 +50,8 @@ export default class SecurityResponse extends KoaResponse {
4850

4951
// if begin with '/', it means an internal jump
5052
if (url[0] === '/' && url[1] !== '\\') {
51-
return this.unsafeRedirect(url, alt);
53+
this.unsafeRedirect(url, alt);
54+
return;
5255
}
5356

5457
let urlObject: URL;

src/config/config.default.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import z from 'zod';
2+
import { Context } from '@eggjs/core';
23

34
const CSRFSupportRequestItem = z.object({
45
path: z.instanceof(RegExp),
@@ -38,7 +39,7 @@ export type SecurityMiddlewareName = z.infer<typeof SecurityMiddlewareName>;
3839
/**
3940
* (ctx) => boolean
4041
*/
41-
const IgnoreOrMatchHandler = z.function().args(z.any()).returns(z.boolean());
42+
const IgnoreOrMatchHandler = z.function().args(z.instanceof(Context)).returns(z.boolean());
4243
export type IgnoreOrMatchHandler = z.infer<typeof IgnoreOrMatchHandler>;
4344

4445
const IgnoreOrMatch = z.union([
@@ -154,7 +155,7 @@ export const SecurityConfig = z.object({
154155
cookieDomain: z.union([
155156
z.string(),
156157
z.function()
157-
.args(z.any())
158+
.args(z.instanceof(Context))
158159
.returns(z.string()),
159160
]).optional(),
160161
/**
@@ -278,7 +279,7 @@ export const SecurityConfig = z.object({
278279
*
279280
* Default to `'1; mode=block'`
280281
*/
281-
value: z.string().default('1; mode=block'),
282+
value: z.coerce.string().default('1; mode=block'),
282283
}).default({}),
283284
/**
284285
* content security policy config

0 commit comments

Comments
 (0)