@startsimpli/ui 0.4.100 → 0.4.101
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/package.json
CHANGED
|
@@ -128,6 +128,30 @@ describe('no-hype', () => {
|
|
|
128
128
|
describe('approved sources', () => {
|
|
129
129
|
const approvedHosts = ['example.com', 'gov.uk'];
|
|
130
130
|
|
|
131
|
+
it('accepts a SUBDOMAIN of an approved domain', () => {
|
|
132
|
+
// Same organisation, own subdomain. Exact-host matching rejected
|
|
133
|
+
// documents.worldbank.org while worldbank.org was approved — on the live
|
|
134
|
+
// OGMC corpus that was the last thing blocking approval on 3 drafts.
|
|
135
|
+
const c = find(
|
|
136
|
+
runContentChecks(
|
|
137
|
+
{ sources: 'https://docs.example.com/a https://a.b.gov.uk/c' },
|
|
138
|
+
{ approvedHosts },
|
|
139
|
+
),
|
|
140
|
+
'approved-sources',
|
|
141
|
+
);
|
|
142
|
+
expect(c?.status).toBe('pass');
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('does NOT accept a domain that merely ENDS WITH an approved one', () => {
|
|
146
|
+
// The dot is load-bearing: `notexample.com` must not pass as `example.com`.
|
|
147
|
+
const c = find(
|
|
148
|
+
runContentChecks({ sources: 'https://notexample.com/a' }, { approvedHosts }),
|
|
149
|
+
'approved-sources',
|
|
150
|
+
);
|
|
151
|
+
expect(c?.status).toBe('fail');
|
|
152
|
+
expect(c?.detail).toContain('notexample.com');
|
|
153
|
+
});
|
|
154
|
+
|
|
131
155
|
it('is skipped entirely when approvedHosts is omitted', () => {
|
|
132
156
|
expect(find(runContentChecks({ sources: 'https://example.com/a' }), 'approved-sources')).toBeUndefined();
|
|
133
157
|
});
|
|
@@ -287,7 +287,22 @@ export function runContentChecks(fields: ContentFields, config: ContentChecksCon
|
|
|
287
287
|
|
|
288
288
|
// Approved sources — only when the app supplied an allow-list.
|
|
289
289
|
if (approvedHosts !== undefined) {
|
|
290
|
-
const approved =
|
|
290
|
+
const approved = approvedHosts.map((h) => h.toLowerCase().replace(/^www\./, ''));
|
|
291
|
+
/**
|
|
292
|
+
* A host is approved when it IS an approved domain or is a SUBDOMAIN of one.
|
|
293
|
+
*
|
|
294
|
+
* Exact equality alone rejected `documents.worldbank.org` while
|
|
295
|
+
* `worldbank.org` was approved, and `eservices.misa.gov.sa` while
|
|
296
|
+
* `misa.gov.sa` was — the same organisation publishing on its own
|
|
297
|
+
* subdomain. On the live OGMC corpus that was the last thing blocking
|
|
298
|
+
* approval on 3 drafts after the source list itself was fixed.
|
|
299
|
+
*
|
|
300
|
+
* The dot in `.${domain}` is load-bearing: without it `notworldbank.org`
|
|
301
|
+
* would match `worldbank.org`, which is exactly the attack a naive
|
|
302
|
+
* `endsWith` invites.
|
|
303
|
+
*/
|
|
304
|
+
const isApproved = (host: string): boolean =>
|
|
305
|
+
approved.some((domain) => host === domain || host.endsWith(`.${domain}`));
|
|
291
306
|
const urls = extractUrls(fields.sources);
|
|
292
307
|
const hosts = urls.map(hostOf).filter(Boolean);
|
|
293
308
|
if (hosts.length === 0) {
|
|
@@ -299,7 +314,7 @@ export function runContentChecks(fields: ContentFields, config: ContentChecksCon
|
|
|
299
314
|
locations: [{ field: 'sources' }],
|
|
300
315
|
});
|
|
301
316
|
} else {
|
|
302
|
-
const bad = Array.from(new Set(hosts.filter((h) => !
|
|
317
|
+
const bad = Array.from(new Set(hosts.filter((h) => !isApproved(h) || FORUM_SOCIAL.test(h))));
|
|
303
318
|
// Highlight the offending URLs as they appear in the sources text — the
|
|
304
319
|
// reviewer pastes URLs, not bare hosts, so matching on the host alone
|
|
305
320
|
// would highlight nothing.
|