mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
fix(agents): reject file bases and preserve quoted URL boundaries
This commit is contained in:
1 parent
802d3dc43c
commit
7b4a49821b
4 files changed
+41
-4
No files matched your search
@@ -66,7 +66,7 @@ The first active HTML base href sets reference resolution, including nested srcd
|
||||
Resolved file URLs use native filesystem conversion, including Windows drive paths.
|
||||
Explicit srcset attributes must contain at least one parsed candidate.
|
||||
Image and media references require a nonempty path that resolves to a file, not a directory.
|
||||
Direct file URLs are rejected; use portable repository-relative paths.
|
||||
Direct file URLs and file-scheme HTML bases are rejected; use portable repository-relative paths.
|
||||
Image references check file existence without interpreting image fragments as
|
||||
Markdown headings; document links keep anchor checks even when sharing a target.
|
||||
HTML video, audio, source and track `src` assets and video posters use the same
|
||||
@@ -77,7 +77,7 @@ At-signs inside external URIs (including explicit opaque autolinks such as mailt
|
||||
per HTML text node, preserving adjacent imports. A colon directly before an import
|
||||
does not make that import a URI. Opaque schemes are excluded only in parsed links
|
||||
whose visible text equals their URI, so colon-labeled prose remains checked.
|
||||
A closing bracket followed by punctuation and an at-sign terminates a bare URL exclusion.
|
||||
A closing bracket or quote followed by punctuation and an at-sign terminates a bare URL exclusion.
|
||||
Extensionless inline candidates are also imports when they resolve to repository files,
|
||||
checking the full filename before prefixes at ASCII/Unicode prose separators,
|
||||
including opening parentheses, brackets and braces. Each at-sign candidate is
|
||||
|
||||
@@ -163,7 +163,7 @@ export function guidanceProse(markdown) {
|
||||
}
|
||||
if (node.nodeName === '#text')
|
||||
return node.value.replace(
|
||||
/(?:\b[a-z][a-z\d+.-]*:\/\/|\/\/)[^\s]*?(?=[)\]}>][.,;:!?]*@|\s|$)/giu,
|
||||
/(?:\b[a-z][a-z\d+.-]*:\/\/|\/\/)[^\s]*?(?=[)\]}>"'”’][.,;:!?]*@|\s|$)/giu,
|
||||
' '
|
||||
);
|
||||
const content = (node.childNodes ?? []).map(text).join('');
|
||||
|
||||
@@ -48,7 +48,11 @@ async function validateReference(
|
||||
if (bases?.length) {
|
||||
try {
|
||||
let base = pathToFileURL(resolve(rootDir, source));
|
||||
for (const href of bases) base = new URL(href, base);
|
||||
for (const href of bases) {
|
||||
if (/^file:/iu.test(href.replace(/[\t\n\r]/gu, '').trimStart()))
|
||||
return `${source}: use a repository-relative HTML base instead of a file URL`;
|
||||
base = new URL(href, base);
|
||||
}
|
||||
const url = new URL(target, base);
|
||||
if (url.protocol !== 'file:') return;
|
||||
resolvedBasePath = fileURLToPath(url);
|
||||
|
||||
@@ -1597,3 +1597,36 @@ for (const markup of [
|
||||
assert.ok((await diagnostics(t, { 'AGENTS.md': markup })).length > 0);
|
||||
});
|
||||
}
|
||||
|
||||
for (const quote of ['"', "'", '”']) {
|
||||
test(`quoted URL preserves adjacent import: ${quote}`, async (t) => {
|
||||
assert.ok(
|
||||
(
|
||||
await diagnostics(t, {
|
||||
'CLAUDE.md':
|
||||
'@AGENTS.md\n\nVisit ' +
|
||||
quote +
|
||||
'https://example.com/path' +
|
||||
quote +
|
||||
'.@docs/guide.md',
|
||||
})
|
||||
).some((message) => message.includes('additional or inline'))
|
||||
);
|
||||
});
|
||||
}
|
||||
for (const embedded of [false, true]) {
|
||||
test(`file URL base is rejected: embedded=${embedded}`, async (t) => {
|
||||
const rootDir = await fixture(t);
|
||||
const { pathToFileURL } = await import('node:url');
|
||||
const { realpath } = await import('node:fs/promises');
|
||||
const base = pathToFileURL((await realpath(rootDir)) + '/').href;
|
||||
const html = `<base href='${base}'><a href='docs/example.md'>Guide</a>`;
|
||||
await writeFile(
|
||||
join(rootDir, 'AGENTS.md'),
|
||||
embedded ? `<iframe srcdoc="${html}"></iframe>` : html
|
||||
);
|
||||
assert.ok(
|
||||
(await validateAgentGuidance({ rootDir })).diagnostics.length > 0
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user