@forge/manifest 3.3.0-next.4 → 3.3.0-next.7
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/CHANGELOG.md +22 -0
- package/out/schema/manifest-schema.json +311 -147
- package/out/schema/manifest.d.ts +260 -160
- package/out/types/egress-types.d.ts +1 -1
- package/out/types/egress-types.d.ts.map +1 -1
- package/out/types/egress-types.js +3 -1
- package/out/validators/permissions-validator.d.ts +6 -0
- package/out/validators/permissions-validator.d.ts.map +1 -1
- package/out/validators/permissions-validator.js +76 -73
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions-validator.d.ts","sourceRoot":"","sources":["../../src/validators/permissions-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AAGrF,OAAO,EAAE,cAAc,EAAU,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAM3D,qBAAa,oBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IACzF,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,wBAAwB,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"permissions-validator.d.ts","sourceRoot":"","sources":["../../src/validators/permissions-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AAGrF,OAAO,EAAE,cAAc,EAAU,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAM3D,qBAAa,oBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IACzF,OAAO,CAAC,gBAAgB,CAAoB;;IAM5C,OAAO,CAAC,UAAU;IA+BlB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,8BAA8B;IAWtC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,wBAAwB,CAAC,cAAc,CAAC;CA8FzG"}
|
|
@@ -9,97 +9,100 @@ const url_1 = require("url");
|
|
|
9
9
|
const shipyard_scopes_json_1 = tslib_1.__importDefault(require("../scopes/shipyard-scopes.json"));
|
|
10
10
|
const deprecated_shipyard_scopes_json_1 = tslib_1.__importDefault(require("../scopes/deprecated-shipyard-scopes.json"));
|
|
11
11
|
class PermissionsValidator {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
constructor() {
|
|
13
|
+
this.validationErrors = [];
|
|
14
|
+
}
|
|
15
|
+
isValidURL(inputURL) {
|
|
16
|
+
const protocolRegex = /^(.*?:\/\/)/;
|
|
17
|
+
const validURI = /^(\*\.)?[.a-zA-Z0-9_\-\/:~#%?=&]+$/;
|
|
18
|
+
const allowedProtocols = ['https:', 'wss:'];
|
|
19
|
+
const MAX_URL_LENGTH = 1000;
|
|
20
|
+
if (inputURL.length > MAX_URL_LENGTH) {
|
|
21
|
+
return false;
|
|
19
22
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
validationErrors.push(Object.assign({ message: text_1.errors.permissions.invalidPermission(element, value), reference: text_1.References.Permissions, level: 'error' }, utils_1.findPosition(value, manifest.yamlContentByLine)));
|
|
23
|
+
if (inputURL === '*') {
|
|
24
|
+
return true;
|
|
23
25
|
}
|
|
26
|
+
if (!inputURL.includes('.') || inputURL.includes(' ')) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const domainOrUrlWithProtocol = protocolRegex.test(inputURL) ? inputURL : `https://${inputURL}`;
|
|
31
|
+
const parsedUrl = new url_1.URL(domainOrUrlWithProtocol);
|
|
32
|
+
if (!allowedProtocols.includes(parsedUrl.protocol)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return validURI.test(parsedUrl.hostname);
|
|
36
|
+
}
|
|
37
|
+
catch (_) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
isValidHash(cspString) {
|
|
24
42
|
const BASE_64_HASH_PATTERNS = [
|
|
25
43
|
/^sha256-[a-zA-Z0-9=+/]{44}$/,
|
|
26
44
|
/^sha384-[a-zA-Z0-9=+/]{64}$/,
|
|
27
45
|
/^sha512-[a-zA-Z0-9=+/]{88}$/
|
|
28
46
|
];
|
|
29
|
-
|
|
30
|
-
|
|
47
|
+
return BASE_64_HASH_PATTERNS.some((pattern) => pattern.test(cspString));
|
|
48
|
+
}
|
|
49
|
+
addValidationErrors(element, values, manifest) {
|
|
50
|
+
values.forEach((value) => {
|
|
51
|
+
this.validationErrors.push(Object.assign({ message: text_1.errors.permissions.invalidPermission(element, value), reference: text_1.References.Permissions, level: 'error' }, utils_1.findPosition(value, manifest.yamlContentByLine)));
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
validateExternalPermissionURLs(extPermType, perms, manifest) {
|
|
55
|
+
const invalidPerms = perms === null || perms === void 0 ? void 0 : perms.filter((key) => !this.isValidURL(key));
|
|
56
|
+
if (invalidPerms === null || invalidPerms === void 0 ? void 0 : invalidPerms.length) {
|
|
57
|
+
this.addValidationErrors(extPermType, invalidPerms, manifest);
|
|
31
58
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
if (inputURL === '*') {
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
if (!inputURL.includes('.') || inputURL.includes(' ')) {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
try {
|
|
47
|
-
const domainOrUrlWithProtocol = protocolRegex.test(inputURL) ? inputURL : `https://${inputURL}`;
|
|
48
|
-
const parsedUrl = new url_1.URL(domainOrUrlWithProtocol);
|
|
49
|
-
if (!allowedProtocols.includes(parsedUrl.protocol)) {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
return validURI.test(parsedUrl.hostname);
|
|
53
|
-
}
|
|
54
|
-
catch (_) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
59
|
+
}
|
|
60
|
+
validate(manifest) {
|
|
61
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
|
|
62
|
+
if (!manifest || !manifest.typedContent || !manifest.typedContent.permissions) {
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
manifestObject: manifest
|
|
66
|
+
};
|
|
57
67
|
}
|
|
58
68
|
const ALL_SCOPES = shipyard_scopes_json_1.default.concat(deprecated_shipyard_scopes_json_1.default);
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
61
|
-
|
|
69
|
+
const invalidScopes = (_a = manifest.typedContent.permissions.scopes) === null || _a === void 0 ? void 0 : _a.filter((key) => !ALL_SCOPES.includes(key));
|
|
70
|
+
if (invalidScopes === null || invalidScopes === void 0 ? void 0 : invalidScopes.length) {
|
|
71
|
+
this.addValidationErrors('scopes', invalidScopes, manifest);
|
|
62
72
|
}
|
|
63
|
-
const invalidScripts = (_c = (_b = manifest.typedContent.permissions.content) === null || _b === void 0 ? void 0 : _b.scripts) === null || _c === void 0 ? void 0 : _c.
|
|
64
|
-
if (invalidScripts) {
|
|
65
|
-
|
|
73
|
+
const invalidScripts = (_c = (_b = manifest.typedContent.permissions.content) === null || _b === void 0 ? void 0 : _b.scripts) === null || _c === void 0 ? void 0 : _c.filter((key) => !egress_types_1.EGRESS_TYPES.ALLOWED_CSP_TYPES.includes(key) && !this.isValidHash(key));
|
|
74
|
+
if (invalidScripts === null || invalidScripts === void 0 ? void 0 : invalidScripts.length) {
|
|
75
|
+
this.addValidationErrors('content.scripts', invalidScripts, manifest);
|
|
66
76
|
}
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
69
|
-
|
|
77
|
+
const invalidBackendStrings = (_f = (_e = (_d = manifest.typedContent.permissions.external) === null || _d === void 0 ? void 0 : _d.fetch) === null || _e === void 0 ? void 0 : _e.backend) === null || _f === void 0 ? void 0 : _f.filter((item) => typeof item === 'string' && !this.isValidURL(item));
|
|
78
|
+
if (invalidBackendStrings === null || invalidBackendStrings === void 0 ? void 0 : invalidBackendStrings.length) {
|
|
79
|
+
this.addValidationErrors('external.fetch.backend', invalidBackendStrings, manifest);
|
|
70
80
|
}
|
|
71
81
|
const remoteMap = (_g = manifest.typedContent.remotes) === null || _g === void 0 ? void 0 : _g.reduce((prev, item) => prev.set(item.key, item.baseUrl), new Map());
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const invalidClientString = (_o = (_m = (_l = manifest.typedContent.permissions.external) === null || _l === void 0 ? void 0 : _l.fetch) === null || _m === void 0 ? void 0 : _m.client) === null || _o === void 0 ? void 0 : _o.filter((item) => typeof item === 'string').find((key) => !isValidURL(key));
|
|
77
|
-
if (invalidClientString) {
|
|
78
|
-
addValidationError('external.fetch.client', invalidClientString, manifest);
|
|
79
|
-
}
|
|
80
|
-
const invalidClient = (_r = (_q = (_p = manifest.typedContent.permissions.external) === null || _p === void 0 ? void 0 : _p.fetch) === null || _q === void 0 ? void 0 : _q.client) === null || _r === void 0 ? void 0 : _r.filter((item) => typeof item === 'object').find((item) => !remoteMap || !remoteMap.has(item.remote) || !isValidURL(remoteMap.get(item.remote)));
|
|
81
|
-
if (invalidClient) {
|
|
82
|
-
addValidationError('external.fetch.client', invalidClient.remote, manifest);
|
|
83
|
-
}
|
|
84
|
-
const invalidNavigation = (_t = (_s = manifest.typedContent.permissions.external) === null || _s === void 0 ? void 0 : _s.navigation) === null || _t === void 0 ? void 0 : _t.find((key) => !isValidURL(key));
|
|
85
|
-
if (invalidNavigation) {
|
|
86
|
-
addValidationError('external.navigation', invalidNavigation, manifest);
|
|
87
|
-
}
|
|
88
|
-
const invalidImages = (_v = (_u = manifest.typedContent.permissions.external) === null || _u === void 0 ? void 0 : _u.images) === null || _v === void 0 ? void 0 : _v.find((key) => !isValidURL(key));
|
|
89
|
-
if (invalidImages) {
|
|
90
|
-
addValidationError('external.images', invalidImages, manifest);
|
|
82
|
+
const invalidBackendRemotes = (_k = (_j = (_h = manifest.typedContent.permissions.external) === null || _h === void 0 ? void 0 : _h.fetch) === null || _j === void 0 ? void 0 : _j.backend) === null || _k === void 0 ? void 0 : _k.filter((item) => typeof item === 'object' &&
|
|
83
|
+
(!remoteMap || !remoteMap.has(item.remote) || !this.isValidURL(remoteMap.get(item.remote)))).map((item) => item.remote);
|
|
84
|
+
if (invalidBackendRemotes === null || invalidBackendRemotes === void 0 ? void 0 : invalidBackendRemotes.length) {
|
|
85
|
+
this.addValidationErrors('external.fetch.backend', invalidBackendRemotes, manifest);
|
|
91
86
|
}
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
|
|
87
|
+
const invalidClientStrings = (_o = (_m = (_l = manifest.typedContent.permissions.external) === null || _l === void 0 ? void 0 : _l.fetch) === null || _m === void 0 ? void 0 : _m.client) === null || _o === void 0 ? void 0 : _o.filter((item) => typeof item === 'string' && !this.isValidURL(item));
|
|
88
|
+
if (invalidClientStrings) {
|
|
89
|
+
this.addValidationErrors('external.fetch.client', invalidClientStrings, manifest);
|
|
95
90
|
}
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
91
|
+
const invalidClients = (_r = (_q = (_p = manifest.typedContent.permissions.external) === null || _p === void 0 ? void 0 : _p.fetch) === null || _q === void 0 ? void 0 : _q.client) === null || _r === void 0 ? void 0 : _r.filter((item) => typeof item === 'object' &&
|
|
92
|
+
(!remoteMap || !remoteMap.has(item.remote) || !this.isValidURL(remoteMap.get(item.remote)))).map((item) => item.remote);
|
|
93
|
+
if (invalidClients) {
|
|
94
|
+
this.addValidationErrors('external.fetch.client', invalidClients, manifest);
|
|
99
95
|
}
|
|
96
|
+
this.validateExternalPermissionURLs('external.navigation', (_s = manifest.typedContent.permissions.external) === null || _s === void 0 ? void 0 : _s.navigation, manifest);
|
|
97
|
+
this.validateExternalPermissionURLs('external.images', (_t = manifest.typedContent.permissions.external) === null || _t === void 0 ? void 0 : _t.images, manifest);
|
|
98
|
+
this.validateExternalPermissionURLs('external.frames', (_u = manifest.typedContent.permissions.external) === null || _u === void 0 ? void 0 : _u.frames, manifest);
|
|
99
|
+
this.validateExternalPermissionURLs('external.scripts', (_v = manifest.typedContent.permissions.external) === null || _v === void 0 ? void 0 : _v.scripts, manifest);
|
|
100
|
+
this.validateExternalPermissionURLs('external.styles', (_w = manifest.typedContent.permissions.external) === null || _w === void 0 ? void 0 : _w.styles, manifest);
|
|
101
|
+
this.validateExternalPermissionURLs('external.media', (_x = manifest.typedContent.permissions.external) === null || _x === void 0 ? void 0 : _x.media, manifest);
|
|
102
|
+
this.validateExternalPermissionURLs('external.fonts', (_y = manifest.typedContent.permissions.external) === null || _y === void 0 ? void 0 : _y.fonts, manifest);
|
|
100
103
|
return {
|
|
101
|
-
success: validationErrors.length === 0,
|
|
102
|
-
errors: validationErrors
|
|
104
|
+
success: this.validationErrors.length === 0,
|
|
105
|
+
errors: this.validationErrors
|
|
103
106
|
};
|
|
104
107
|
}
|
|
105
108
|
}
|