-
Notifications
You must be signed in to change notification settings - Fork 2
Add glob support for lcov-file-paths
#18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| import { promises as fs } from 'node:fs'; | ||
| import os from 'node:os'; | ||
| import path from 'node:path'; | ||
| import { resolveLcovFilePaths } from '../src/resolveLcovFilePaths.js'; | ||
|
|
||
| describe('resolveLcovFilePaths', () => { | ||
| let tmpDir; | ||
| let previousCwd; | ||
|
|
||
| beforeEach(async () => { | ||
| tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'resolve-lcov-')); | ||
| previousCwd = process.cwd(); | ||
| process.chdir(tmpDir); | ||
| }); | ||
|
|
||
| afterEach(async () => { | ||
| process.chdir(previousCwd); | ||
| await fs.rm(tmpDir, { recursive: true, force: true }); | ||
| }); | ||
|
|
||
| it('resolves a literal path', async () => { | ||
| await fs.writeFile('lcov.info', ''); | ||
|
|
||
| const resolved = await resolveLcovFilePaths(['lcov.info']); | ||
|
|
||
| expect(resolved).toEqual([path.join(tmpDir, 'lcov.info')]); | ||
| }); | ||
|
|
||
| it('expands a glob pattern to every matching file', async () => { | ||
| await fs.mkdir('packages/a/coverage', { recursive: true }); | ||
| await fs.mkdir('packages/b/coverage', { recursive: true }); | ||
| await fs.writeFile('packages/a/coverage/lcov.info', ''); | ||
| await fs.writeFile('packages/b/coverage/lcov.info', ''); | ||
|
|
||
| const resolved = await resolveLcovFilePaths(['packages/*/coverage/lcov.info']); | ||
|
|
||
| expect(resolved.sort()).toEqual( | ||
| [ | ||
| path.join(tmpDir, 'packages/a/coverage/lcov.info'), | ||
| path.join(tmpDir, 'packages/b/coverage/lcov.info'), | ||
| ].sort(), | ||
| ); | ||
| }); | ||
|
|
||
| it('deduplicates files matched by overlapping patterns', async () => { | ||
| await fs.mkdir('coverage', { recursive: true }); | ||
| await fs.writeFile('coverage/lcov.info', ''); | ||
|
|
||
| const resolved = await resolveLcovFilePaths(['coverage/lcov.info', 'coverage/*.info']); | ||
|
|
||
| expect(resolved).toEqual([path.join(tmpDir, 'coverage/lcov.info')]); | ||
| }); | ||
|
|
||
| it('throws when a pattern matches no files', async () => { | ||
| await expect(resolveLcovFilePaths(['packages/*/coverage/lcov.info'])).rejects.toThrow( | ||
| /No file\(s\) found matching "packages\/\*\/coverage\/lcov.info"/, | ||
| ); | ||
| }); | ||
|
|
||
| it('rejects an absolute pattern', async () => { | ||
| await expect(resolveLcovFilePaths(['/etc/passwd'])).rejects.toThrow( | ||
| /Invalid file path: absolute paths and "\.\." segments are not allowed/, | ||
| ); | ||
| }); | ||
|
|
||
| it('rejects a pattern containing ".." segments', async () => { | ||
| await expect(resolveLcovFilePaths(['../etc/passwd'])).rejects.toThrow( | ||
| /Invalid file path: absolute paths and "\.\." segments are not allowed/, | ||
| ); | ||
| }); | ||
|
|
||
| it('rejects a matched file that is a symlink outside the workspace', async () => { | ||
| const secret = await fs.mkdtemp(path.join(os.tmpdir(), 'resolve-lcov-secret-')); | ||
| await fs.writeFile(path.join(secret, 'passwd'), 'root:x:0:0'); | ||
| await fs.symlink(path.join(secret, 'passwd'), 'coverage.info'); | ||
|
|
||
| try { | ||
| await expect(resolveLcovFilePaths(['coverage.info'])).rejects.toThrow( | ||
| /matched a symlink, which is not allowed/, | ||
| ); | ||
| } finally { | ||
| await fs.rm(secret, { recursive: true, force: true }); | ||
| } | ||
| }); | ||
| }); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,10 +14,6 @@ export async function mergeLcov(paths) { | |
| const contents = []; | ||
|
|
||
| for (const inputPath of paths) { | ||
| if (inputPath.includes('..') || path.isAbsolute(inputPath)) { | ||
| throw new Error('Invalid file path'); | ||
| } | ||
|
|
||
| contents.push(await fs.readFile(path.resolve(inputPath), 'utf8')); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potential file inclusion attack via reading file - medium severity Show fixRemediation: Ignore this issue only after you've verified or sanitized the input going into this function. This issue is only relevant in the backend, not in the frontend! Reply |
||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.