@zappie/check 0.2.1 → 0.2.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/CHANGELOG.md +25 -0
- package/dist/index.js +49 -11
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @zappie/check
|
|
2
2
|
|
|
3
|
+
## 0.2.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9b25eb7: The packages now live in zappie/storefront-packages, and each package's repository, homepage and issues links point there. This release is the first one published from that repository.
|
|
8
|
+
- Updated dependencies [9b25eb7]
|
|
9
|
+
- @zappie/sdk@0.1.13
|
|
10
|
+
- @zappie/tokens@0.1.2
|
|
11
|
+
- eslint-plugin-zappie@0.3.1
|
|
12
|
+
|
|
13
|
+
## 0.2.2
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- afb46d4: Add storefront security lint rules, pass outbound hosts from `zappie.config.ts` to ESLint, and provide `safeRedirect` from `@zappie/sdk/redirect` for untrusted navigation targets.
|
|
18
|
+
- Updated dependencies [2b672c9]
|
|
19
|
+
- Updated dependencies [9b5b412]
|
|
20
|
+
- Updated dependencies [32ecccf]
|
|
21
|
+
- Updated dependencies [afb46d4]
|
|
22
|
+
- Updated dependencies [6a8e227]
|
|
23
|
+
- Updated dependencies [c0171ae]
|
|
24
|
+
- Updated dependencies [0cbc4da]
|
|
25
|
+
- @zappie/sdk@0.1.12
|
|
26
|
+
- eslint-plugin-zappie@0.3.0
|
|
27
|
+
|
|
3
28
|
## 0.2.1
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -67,7 +67,7 @@ var globallyAllowed = (value) => GLOBAL_PACKAGE_ALLOWLIST.some(
|
|
|
67
67
|
function hostname(value) {
|
|
68
68
|
const wildcard = value.startsWith("*.");
|
|
69
69
|
const host = wildcard ? value.slice(2) : value;
|
|
70
|
-
if (!host.includes(".") || /^\d+(?:\.\d+){3}$/.test(host) || host.length > 253 || host.includes("..")) {
|
|
70
|
+
if (!host.includes(".") || /^\d+(?:\.\d+){3}$/.test(host) || host.length > 253 || host.includes("..") || wildcard && /^(?:ac|co|com|edu|gov|net|org)\.[^.]+$/i.test(host)) {
|
|
71
71
|
return false;
|
|
72
72
|
}
|
|
73
73
|
return host.split(".").every(
|
|
@@ -183,6 +183,7 @@ var rootKeys = [
|
|
|
183
183
|
"packages",
|
|
184
184
|
"audit",
|
|
185
185
|
"outbound",
|
|
186
|
+
"security",
|
|
186
187
|
"budgets",
|
|
187
188
|
"readiness",
|
|
188
189
|
"analytics"
|
|
@@ -236,16 +237,20 @@ function validateConfig(input) {
|
|
|
236
237
|
});
|
|
237
238
|
});
|
|
238
239
|
nested(input.outbound, "outbound", ["allow"], issue, (value) => {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
240
|
+
hostList(value.allow, "outbound.allow", error);
|
|
241
|
+
});
|
|
242
|
+
nested(input.security, "security", ["csp"], issue, (security) => {
|
|
243
|
+
nested(
|
|
244
|
+
security.csp,
|
|
245
|
+
"security.csp",
|
|
246
|
+
["imgSrc", "connectSrc", "fontSrc", "styleSrc", "frameSrc"],
|
|
247
|
+
issue,
|
|
248
|
+
(csp) => {
|
|
249
|
+
for (const [name, value] of Object.entries(csp)) {
|
|
250
|
+
hostList(value, `security.csp.${name}`, error);
|
|
251
|
+
}
|
|
247
252
|
}
|
|
248
|
-
|
|
253
|
+
);
|
|
249
254
|
});
|
|
250
255
|
budgets(input.budgets, issue, error);
|
|
251
256
|
nested(
|
|
@@ -346,6 +351,17 @@ function stringList(value, path15, error, options = {}) {
|
|
|
346
351
|
}
|
|
347
352
|
return value;
|
|
348
353
|
}
|
|
354
|
+
function hostList(value, path15, error) {
|
|
355
|
+
stringList(value, path15, error)?.forEach((host, index) => {
|
|
356
|
+
if (!hostname(host)) {
|
|
357
|
+
error(
|
|
358
|
+
`${path15}[${index}]`,
|
|
359
|
+
"invalid_format",
|
|
360
|
+
"Expected a hostname or leading *. subdomain pattern without a scheme, path, port or IP. Use a value such as api.example.com."
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
}
|
|
349
365
|
function paths(value, error) {
|
|
350
366
|
const values = stringList(value, "prerender", error, { unique: true });
|
|
351
367
|
values?.forEach((path15, index) => {
|
|
@@ -2784,7 +2800,12 @@ async function checkLint({
|
|
|
2784
2800
|
]);
|
|
2785
2801
|
}
|
|
2786
2802
|
try {
|
|
2787
|
-
const eslint = new ESLint({
|
|
2803
|
+
const eslint = new ESLint({
|
|
2804
|
+
cwd,
|
|
2805
|
+
overrideConfig: {
|
|
2806
|
+
settings: { zappie: { outboundAllow: await outboundAllow(cwd) } }
|
|
2807
|
+
}
|
|
2808
|
+
});
|
|
2788
2809
|
const source = await sourceFile(cwd);
|
|
2789
2810
|
const config = await eslint.calculateConfigForFile(source);
|
|
2790
2811
|
const problems = recommendedProblems(config?.rules ?? {});
|
|
@@ -2818,6 +2839,23 @@ async function checkLint({
|
|
|
2818
2839
|
]);
|
|
2819
2840
|
}
|
|
2820
2841
|
}
|
|
2842
|
+
async function outboundAllow(cwd) {
|
|
2843
|
+
try {
|
|
2844
|
+
const value = (await loadConfig(cwd)).value;
|
|
2845
|
+
if (!value || typeof value !== "object" || !("outbound" in value)) {
|
|
2846
|
+
return [];
|
|
2847
|
+
}
|
|
2848
|
+
const outbound = value.outbound;
|
|
2849
|
+
if (!outbound || typeof outbound !== "object" || !("allow" in outbound)) {
|
|
2850
|
+
return [];
|
|
2851
|
+
}
|
|
2852
|
+
return Array.isArray(outbound.allow) ? outbound.allow.filter(
|
|
2853
|
+
(entry) => typeof entry === "string"
|
|
2854
|
+
) : [];
|
|
2855
|
+
} catch {
|
|
2856
|
+
return [];
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2821
2859
|
function recommendedProblems(applied) {
|
|
2822
2860
|
const expected = recommendedRules();
|
|
2823
2861
|
return Object.entries(expected).flatMap(([rule, severity]) => {
|