mirror of
https://github.com/actions/toolkit.git
synced 2026-08-14 00:00:18 +02:00
Fix lint issues
This commit is contained in:
+4
-16
@@ -125,10 +125,7 @@ describe('listAndValidate (real archives)', () => {
|
|||||||
const archive = buildTarArchive([
|
const archive = buildTarArchive([
|
||||||
{path: 'cache/file.txt', type: 'File', body: Buffer.from('hi')}
|
{path: 'cache/file.txt', type: 'File', body: Buffer.from('hi')}
|
||||||
])
|
])
|
||||||
const archivePath = writeArchive(
|
const archivePath = writeArchive('clean.tar.gz', zlib.gzipSync(archive))
|
||||||
'clean.tar.gz',
|
|
||||||
zlib.gzipSync(archive)
|
|
||||||
)
|
|
||||||
const violations = await listAndValidate(
|
const violations = await listAndValidate(
|
||||||
archivePath,
|
archivePath,
|
||||||
CompressionMethod.Gzip,
|
CompressionMethod.Gzip,
|
||||||
@@ -259,10 +256,7 @@ describe('listAndValidate (real archives)', () => {
|
|||||||
},
|
},
|
||||||
{path: 'cache/sub/c.txt', type: 'File', body: Buffer.from('4')}
|
{path: 'cache/sub/c.txt', type: 'File', body: Buffer.from('4')}
|
||||||
])
|
])
|
||||||
const archivePath = writeArchive(
|
const archivePath = writeArchive('mixed.tar.gz', zlib.gzipSync(archive))
|
||||||
'mixed.tar.gz',
|
|
||||||
zlib.gzipSync(archive)
|
|
||||||
)
|
|
||||||
const violations = await listAndValidate(
|
const violations = await listAndValidate(
|
||||||
archivePath,
|
archivePath,
|
||||||
CompressionMethod.Gzip,
|
CompressionMethod.Gzip,
|
||||||
@@ -277,10 +271,7 @@ describe('listAndValidate (real archives)', () => {
|
|||||||
const archive = buildTarArchive([
|
const archive = buildTarArchive([
|
||||||
{path: 'cache/dev', type: 'CharacterDevice'}
|
{path: 'cache/dev', type: 'CharacterDevice'}
|
||||||
])
|
])
|
||||||
const archivePath = writeArchive(
|
const archivePath = writeArchive('chardev.tar.gz', zlib.gzipSync(archive))
|
||||||
'chardev.tar.gz',
|
|
||||||
zlib.gzipSync(archive)
|
|
||||||
)
|
|
||||||
const violations = await listAndValidate(
|
const violations = await listAndValidate(
|
||||||
archivePath,
|
archivePath,
|
||||||
CompressionMethod.Gzip,
|
CompressionMethod.Gzip,
|
||||||
@@ -295,10 +286,7 @@ describe('listAndValidate (real archives)', () => {
|
|||||||
const archive = buildTarArchive([
|
const archive = buildTarArchive([
|
||||||
{path: 'cache/tiny.txt', type: 'File', body: Buffer.from('1')}
|
{path: 'cache/tiny.txt', type: 'File', body: Buffer.from('1')}
|
||||||
])
|
])
|
||||||
const archivePath = writeArchive(
|
const archivePath = writeArchive('single.tar.gz', zlib.gzipSync(archive))
|
||||||
'single.tar.gz',
|
|
||||||
zlib.gzipSync(archive)
|
|
||||||
)
|
|
||||||
const violations = await listAndValidate(
|
const violations = await listAndValidate(
|
||||||
archivePath,
|
archivePath,
|
||||||
CompressionMethod.Gzip,
|
CompressionMethod.Gzip,
|
||||||
|
|||||||
+19
-27
@@ -8,7 +8,8 @@ import {
|
|||||||
} from '../src/internal/pathValidation'
|
} from '../src/internal/pathValidation'
|
||||||
|
|
||||||
const IS_WINDOWS = process.platform === 'win32'
|
const IS_WINDOWS = process.platform === 'win32'
|
||||||
const CASE_INSENSITIVE = process.platform === 'win32' || process.platform === 'darwin'
|
const CASE_INSENSITIVE =
|
||||||
|
process.platform === 'win32' || process.platform === 'darwin'
|
||||||
|
|
||||||
describe('deriveAllowedRoots', () => {
|
describe('deriveAllowedRoots', () => {
|
||||||
const cwd = IS_WINDOWS ? 'C:\\workspace' : '/workspace'
|
const cwd = IS_WINDOWS ? 'C:\\workspace' : '/workspace'
|
||||||
@@ -63,9 +64,7 @@ describe('deriveAllowedRoots', () => {
|
|||||||
|
|
||||||
describe('negation handling', () => {
|
describe('negation handling', () => {
|
||||||
test('negation pattern (! prefix) is dropped from allowed roots', () => {
|
test('negation pattern (! prefix) is dropped from allowed roots', () => {
|
||||||
const input = IS_WINDOWS
|
const input = IS_WINDOWS ? ['!C:\\foo\\secret'] : ['!/foo/secret']
|
||||||
? ['!C:\\foo\\secret']
|
|
||||||
: ['!/foo/secret']
|
|
||||||
expect(deriveAllowedRoots(input, cwd)).toEqual([])
|
expect(deriveAllowedRoots(input, cwd)).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -107,9 +106,9 @@ describe('deriveAllowedRoots', () => {
|
|||||||
process.env['CACHE_TEST_ROOT'] = IS_WINDOWS ? 'C:\\envroot' : '/envroot'
|
process.env['CACHE_TEST_ROOT'] = IS_WINDOWS ? 'C:\\envroot' : '/envroot'
|
||||||
try {
|
try {
|
||||||
const expected = IS_WINDOWS ? 'C:\\envroot\\sub' : '/envroot/sub'
|
const expected = IS_WINDOWS ? 'C:\\envroot\\sub' : '/envroot/sub'
|
||||||
expect(
|
expect(deriveAllowedRoots(['${CACHE_TEST_ROOT}/sub'], cwd)).toEqual([
|
||||||
deriveAllowedRoots(['${CACHE_TEST_ROOT}/sub'], cwd)
|
expected
|
||||||
).toEqual([expected])
|
])
|
||||||
} finally {
|
} finally {
|
||||||
if (original === undefined) delete process.env['CACHE_TEST_ROOT']
|
if (original === undefined) delete process.env['CACHE_TEST_ROOT']
|
||||||
else process.env['CACHE_TEST_ROOT'] = original
|
else process.env['CACHE_TEST_ROOT'] = original
|
||||||
@@ -132,12 +131,14 @@ describe('deriveAllowedRoots', () => {
|
|||||||
|
|
||||||
test('%VAR% Windows-style expands an environment variable', () => {
|
test('%VAR% Windows-style expands an environment variable', () => {
|
||||||
const original = process.env['CACHE_TEST_WIN_ROOT']
|
const original = process.env['CACHE_TEST_WIN_ROOT']
|
||||||
process.env['CACHE_TEST_WIN_ROOT'] = IS_WINDOWS ? 'C:\\winroot' : '/winroot'
|
process.env['CACHE_TEST_WIN_ROOT'] = IS_WINDOWS
|
||||||
|
? 'C:\\winroot'
|
||||||
|
: '/winroot'
|
||||||
try {
|
try {
|
||||||
const expected = IS_WINDOWS ? 'C:\\winroot\\sub' : '/winroot/sub'
|
const expected = IS_WINDOWS ? 'C:\\winroot\\sub' : '/winroot/sub'
|
||||||
expect(
|
expect(deriveAllowedRoots(['%CACHE_TEST_WIN_ROOT%/sub'], cwd)).toEqual([
|
||||||
deriveAllowedRoots(['%CACHE_TEST_WIN_ROOT%/sub'], cwd)
|
expected
|
||||||
).toEqual([expected])
|
])
|
||||||
} finally {
|
} finally {
|
||||||
if (original === undefined) delete process.env['CACHE_TEST_WIN_ROOT']
|
if (original === undefined) delete process.env['CACHE_TEST_WIN_ROOT']
|
||||||
else process.env['CACHE_TEST_WIN_ROOT'] = original
|
else process.env['CACHE_TEST_WIN_ROOT'] = original
|
||||||
@@ -170,9 +171,9 @@ describe('deriveAllowedRoots', () => {
|
|||||||
const expected = IS_WINDOWS
|
const expected = IS_WINDOWS
|
||||||
? 'C:\\envroot*odd\\sub'
|
? 'C:\\envroot*odd\\sub'
|
||||||
: '/envroot*odd/sub'
|
: '/envroot*odd/sub'
|
||||||
expect(
|
expect(deriveAllowedRoots(['${CACHE_TEST_ROOT}/sub'], cwd)).toEqual([
|
||||||
deriveAllowedRoots(['${CACHE_TEST_ROOT}/sub'], cwd)
|
expected
|
||||||
).toEqual([expected])
|
])
|
||||||
} finally {
|
} finally {
|
||||||
if (original === undefined) delete process.env['CACHE_TEST_ROOT']
|
if (original === undefined) delete process.env['CACHE_TEST_ROOT']
|
||||||
else process.env['CACHE_TEST_ROOT'] = original
|
else process.env['CACHE_TEST_ROOT'] = original
|
||||||
@@ -290,7 +291,7 @@ describe('validateEntry', () => {
|
|||||||
|
|
||||||
test('deeply nested file', () => {
|
test('deeply nested file', () => {
|
||||||
const r = validateEntry(
|
const r = validateEntry(
|
||||||
'node_modules/' + Array(50).fill('sub').join('/') + '/foo.js',
|
`node_modules/${Array(50).fill('sub').join('/')}/foo.js`,
|
||||||
undefined,
|
undefined,
|
||||||
'File',
|
'File',
|
||||||
allowedRoots,
|
allowedRoots,
|
||||||
@@ -379,7 +380,7 @@ describe('validateEntry', () => {
|
|||||||
test('filename containing .. as substring (not segment)', () => {
|
test('filename containing .. as substring (not segment)', () => {
|
||||||
for (const name of ['..hidden', 'file..txt', 'a..b/c']) {
|
for (const name of ['..hidden', 'file..txt', 'a..b/c']) {
|
||||||
const r = validateEntry(
|
const r = validateEntry(
|
||||||
'node_modules/' + name,
|
`node_modules/${name}`,
|
||||||
undefined,
|
undefined,
|
||||||
'File',
|
'File',
|
||||||
allowedRoots,
|
allowedRoots,
|
||||||
@@ -529,13 +530,7 @@ describe('validateEntry', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('Windows drive-relative (no slash)', () => {
|
test('Windows drive-relative (no slash)', () => {
|
||||||
const r = validateEntry(
|
const r = validateEntry('C:foo', undefined, 'File', allowedRoots, cwd)
|
||||||
'C:foo',
|
|
||||||
undefined,
|
|
||||||
'File',
|
|
||||||
allowedRoots,
|
|
||||||
cwd
|
|
||||||
)
|
|
||||||
expect(r.ok).toBe(false)
|
expect(r.ok).toBe(false)
|
||||||
if (!r.ok) expect(r.code).toBe('ABSOLUTE_PATH')
|
if (!r.ok) expect(r.code).toBe('ABSOLUTE_PATH')
|
||||||
})
|
})
|
||||||
@@ -1069,10 +1064,7 @@ describe('formatViolationSummary', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('shows up to maxShown items verbatim', () => {
|
test('shows up to maxShown items verbatim', () => {
|
||||||
const out = formatViolationSummary(
|
const out = formatViolationSummary([v('a'), v('b'), v('c')], 5)
|
||||||
[v('a'), v('b'), v('c')],
|
|
||||||
5
|
|
||||||
)
|
|
||||||
expect(out).toContain(' - a')
|
expect(out).toContain(' - a')
|
||||||
expect(out).toContain(' - b')
|
expect(out).toContain(' - b')
|
||||||
expect(out).toContain(' - c')
|
expect(out).toContain(' - c')
|
||||||
|
|||||||
+3
-9
@@ -203,9 +203,7 @@ describe('extractTar path validation integration', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('clean archive: no throw, extraction proceeds normally', async () => {
|
test('clean archive: no throw, extraction proceeds normally', async () => {
|
||||||
jest
|
jest.spyOn(listAndValidate, 'listAndValidate').mockResolvedValue([])
|
||||||
.spyOn(listAndValidate, 'listAndValidate')
|
|
||||||
.mockResolvedValue([])
|
|
||||||
const warnSpy = jest.spyOn(core, 'warning').mockImplementation()
|
const warnSpy = jest.spyOn(core, 'warning').mockImplementation()
|
||||||
const execMock = jest.spyOn(exec, 'exec').mockResolvedValue(0)
|
const execMock = jest.spyOn(exec, 'exec').mockResolvedValue(0)
|
||||||
|
|
||||||
@@ -234,9 +232,7 @@ describe('extractTar path validation integration', () => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
expect(err).toBeInstanceOf(CacheIntegrityError)
|
expect(err).toBeInstanceOf(CacheIntegrityError)
|
||||||
expect((err as CacheIntegrityError).code).toBe('PARSE_ERROR')
|
expect((err as CacheIntegrityError).code).toBe('PARSE_ERROR')
|
||||||
expect((err as CacheIntegrityError).message).toMatch(
|
expect((err as CacheIntegrityError).message).toMatch(/tar parse error/)
|
||||||
/tar parse error/
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
expect(execMock).not.toHaveBeenCalled()
|
expect(execMock).not.toHaveBeenCalled()
|
||||||
expect(mkdirMock).not.toHaveBeenCalled()
|
expect(mkdirMock).not.toHaveBeenCalled()
|
||||||
@@ -341,9 +337,7 @@ describe('extractTar path validation integration', () => {
|
|||||||
pathValidation: 'warn'
|
pathValidation: 'warn'
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(listMock.mock.calls[0][1]).toBe(
|
expect(listMock.mock.calls[0][1]).toBe(CompressionMethod.ZstdWithoutLong)
|
||||||
CompressionMethod.ZstdWithoutLong
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Vendored
+1
-3
@@ -17,9 +17,7 @@ import {HttpClientError} from '@actions/http-client'
|
|||||||
|
|
||||||
export type {DownloadOptions, UploadOptions}
|
export type {DownloadOptions, UploadOptions}
|
||||||
export {CacheIntegrityError}
|
export {CacheIntegrityError}
|
||||||
export type {
|
export type {CacheIntegrityErrorCode} from './internal/cacheIntegrityError.js'
|
||||||
CacheIntegrityErrorCode
|
|
||||||
} from './internal/cacheIntegrityError.js'
|
|
||||||
export type {
|
export type {
|
||||||
PathValidationMode,
|
PathValidationMode,
|
||||||
PathValidationViolation
|
PathValidationViolation
|
||||||
|
|||||||
+1
-3
@@ -172,9 +172,7 @@ async function streamArchiveTo(
|
|||||||
const tail = stderrTruncated ? ' (stderr truncated)' : ''
|
const tail = stderrTruncated ? ' (stderr truncated)' : ''
|
||||||
reject(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
`zstd ${cause}${
|
`zstd ${cause}${zstdStderr ? `: ${zstdStderr.trim()}` : ''}${tail}`
|
||||||
zstdStderr ? `: ${zstdStderr.trim()}` : ''
|
|
||||||
}${tail}`
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-9
@@ -55,7 +55,7 @@ export type ValidationResult =
|
|||||||
*/
|
*/
|
||||||
export interface PreparedAllowedRoots {
|
export interface PreparedAllowedRoots {
|
||||||
readonly caseInsensitive: boolean
|
readonly caseInsensitive: boolean
|
||||||
readonly roots: ReadonlyArray<PreparedRoot>
|
readonly roots: readonly PreparedRoot[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PreparedRoot {
|
interface PreparedRoot {
|
||||||
@@ -231,7 +231,10 @@ function segmentHasGlob(seg: string): boolean {
|
|||||||
function expandEnvVars(input: string): string {
|
function expandEnvVars(input: string): string {
|
||||||
let result = input
|
let result = input
|
||||||
// ${VAR} — see segmentHasGlob for the polynomial-redos rationale.
|
// ${VAR} — see segmentHasGlob for the polynomial-redos rationale.
|
||||||
result = result.replace(/\$\{([^}]+)\}/g, (_, name) => process.env[name] ?? '') // lgtm[js/polynomial-redos]
|
result = result.replace(
|
||||||
|
/\$\{([^}]+)\}/g,
|
||||||
|
(_, name) => process.env[name] ?? ''
|
||||||
|
) // lgtm[js/polynomial-redos]
|
||||||
// $VAR (POSIX-style identifier)
|
// $VAR (POSIX-style identifier)
|
||||||
result = result.replace(
|
result = result.replace(
|
||||||
/\$([A-Za-z_][A-Za-z0-9_]*)/g,
|
/\$([A-Za-z_][A-Za-z0-9_]*)/g,
|
||||||
@@ -456,13 +459,6 @@ function resolveEntry(entryPath: string, extractCwd: string): string {
|
|||||||
return path.resolve(extractCwd, native)
|
return path.resolve(extractCwd, native)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isUnderAnyRoot(resolved: string, roots: string[]): boolean {
|
|
||||||
for (const root of roots) {
|
|
||||||
if (isUnderRoot(resolved, root)) return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Precompute a {@link PreparedAllowedRoots} from a raw roots array. Call
|
* Precompute a {@link PreparedAllowedRoots} from a raw roots array. Call
|
||||||
* once per `listAndValidate` invocation and reuse for every entry.
|
* once per `listAndValidate` invocation and reuse for every entry.
|
||||||
|
|||||||
Vendored
+3
-4
@@ -374,10 +374,9 @@ function reportViolations(
|
|||||||
core.info(formatViolationSummary(violations))
|
core.info(formatViolationSummary(violations))
|
||||||
for (const v of violations) {
|
for (const v of violations) {
|
||||||
core.debug(
|
core.debug(
|
||||||
`path-validation: code=${v.code} type=${v.entryType} path=${v.path}` +
|
`path-validation: code=${v.code} type=${v.entryType} path=${v.path}${
|
||||||
(v.linkpath ? ` linkpath=${v.linkpath}` : '') +
|
v.linkpath ? ` linkpath=${v.linkpath}` : ''
|
||||||
` resolved=${v.resolved}` +
|
} resolved=${v.resolved} reason=${v.reason}`
|
||||||
` reason=${v.reason}`
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user