mirror of
https://github.com/shivammathur/setup-php.git
synced 2026-09-20 18:07:26 +07:00
Require full tool versions for checksum pinning
This commit is contained in:
@@ -272,7 +272,7 @@ These tools can be set up globally using the `tools` input. It accepts a string
|
|||||||
tools: composer:2.9.8@sha256:59b2c50e10cafa0d8efc19ede9a326d782f096c674a26baf98cf042ce23de890
|
tools: composer:2.9.8@sha256:59b2c50e10cafa0d8efc19ede9a326d782f096c674a26baf98cf042ce23de890
|
||||||
```
|
```
|
||||||
|
|
||||||
Checksum verification is supported for tools which are downloaded as phar archives. It is not supported for tools set up using `composer` packages or custom package scripts, specifying a checksum for these tools will result in an error. For checksum pinning to be effective, pin the tool to an exact version, as mutable versions like `latest` or `major.minor` can resolve to a different release with a different checksum.
|
Checksum verification is supported only for tools downloaded as phar archives with a full version, such as `tool:1.2.3` or `tool:1.2.3-beta1`. Specifying a checksum with an omitted version, a variable tag such as `latest`, `stable`, `preview` or `snapshot`, or a partial version such as `2`, `2.x`, `2.9` or `2.9.x` results in an error. These versions can resolve to different releases with different checksums. Checksum verification is not supported for tools set up using `composer` packages or custom package scripts; specifying a checksum for these tools also results in an error.
|
||||||
|
|
||||||
- The latest stable version of `composer` is set up by default. You can set up the required `composer` version by specifying the major version `v1` or `v2`, or the version in `major.minor` or `semver` format. Additionally, for composer `snapshot` and `preview` can also be specified to set up the respective releases.
|
- The latest stable version of `composer` is set up by default. You can set up the required `composer` version by specifying the major version `v1` or `v2`, or the version in `major.minor` or `semver` format. Additionally, for composer `snapshot` and `preview` can also be specified to set up the respective releases.
|
||||||
|
|
||||||
|
|||||||
+54
-15
@@ -222,20 +222,21 @@ describe('Tools tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it.each`
|
it.each`
|
||||||
release | expected_release | checksum | error
|
release | expected_release | checksum | error
|
||||||
${'tool:1.2.3'} | ${'tool:1.2.3'} | ${undefined} | ${undefined}
|
${'tool:1.2.3'} | ${'tool:1.2.3'} | ${undefined} | ${undefined}
|
||||||
${'tool:1.2.3@sha256:' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
|
${'tool:1.2.3@sha256:' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
|
||||||
${'tool:1.2.3@sha256:' + 'A'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
|
${'tool:1.2.3@sha256:' + 'A'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
|
||||||
${'tool:1.2.3@SHA256:' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
|
${'tool:1.2.3@SHA256:' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
|
||||||
${'tool:1.2.3@sha512:' + 'b'.repeat(128)} | ${'tool:1.2.3'} | ${'sha512:' + 'b'.repeat(128)} | ${undefined}
|
${'tool:1.2.3@sha512:' + 'b'.repeat(128)} | ${'tool:1.2.3'} | ${'sha512:' + 'b'.repeat(128)} | ${undefined}
|
||||||
${'composer:2.9.8@sha256:' + 'c'.repeat(64)} | ${'composer:2.9.8'} | ${'sha256:' + 'c'.repeat(64)} | ${undefined}
|
${'tool:v1.2.3-beta.1+build.2@sha256:' + 'a'.repeat(64)} | ${'tool:v1.2.3-beta.1+build.2'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
|
||||||
${'tool:1.2.3@sha256:xyz'} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha256 checksum, expected 64 hexadecimal characters'}
|
${'composer:2.9.8@sha256:' + 'c'.repeat(64)} | ${'composer:2.9.8'} | ${'sha256:' + 'c'.repeat(64)} | ${undefined}
|
||||||
${'tool:1.2.3@sha256:' + 'a'.repeat(63)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha256 checksum, expected 64 hexadecimal characters'}
|
${'tool:1.2.3@sha256:xyz'} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha256 checksum, expected 64 hexadecimal characters'}
|
||||||
${'tool:1.2.3@sha512:' + 'b'.repeat(64)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha512 checksum, expected 128 hexadecimal characters'}
|
${'tool:1.2.3@sha256:' + 'a'.repeat(63)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha256 checksum, expected 64 hexadecimal characters'}
|
||||||
${'tool:1.2.3@sha384:' + 'b'.repeat(96)} | ${'tool:1.2.3'} | ${undefined} | ${'Unsupported checksum algorithm sha384, expected sha256 or sha512'}
|
${'tool:1.2.3@sha512:' + 'b'.repeat(64)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha512 checksum, expected 128 hexadecimal characters'}
|
||||||
${'tool:1.2.3@md5:' + 'b'.repeat(32)} | ${'tool:1.2.3'} | ${undefined} | ${'Unsupported checksum algorithm md5, expected sha256 or sha512'}
|
${'tool:1.2.3@sha384:' + 'b'.repeat(96)} | ${'tool:1.2.3'} | ${undefined} | ${'Unsupported checksum algorithm sha384, expected sha256 or sha512'}
|
||||||
${'tool:1.2.3@sha256' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid checksum syntax, expected @sha256:<hash> or @sha512:<hash>'}
|
${'tool:1.2.3@md5:' + 'b'.repeat(32)} | ${'tool:1.2.3'} | ${undefined} | ${'Unsupported checksum algorithm md5, expected sha256 or sha512'}
|
||||||
${'tool:1.0@dev'} | ${'tool:1.0@dev'} | ${undefined} | ${undefined}
|
${'tool:1.2.3@sha256' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid checksum syntax, expected @sha256:<hash> or @sha512:<hash>'}
|
||||||
|
${'tool:1.0@dev'} | ${'tool:1.0@dev'} | ${undefined} | ${undefined}
|
||||||
`(
|
`(
|
||||||
'checking extractChecksum: $release',
|
'checking extractChecksum: $release',
|
||||||
({release, expected_release, checksum, error}) => {
|
({release, expected_release, checksum, error}) => {
|
||||||
@@ -836,7 +837,7 @@ describe('Tools tests', () => {
|
|||||||
${'cs2pr:1.2.3@sha256:' + 'd'.repeat(64)} | ${'linux'} | ${'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/download/1.2.3/cs2pr cs2pr "-V" sha256:' + 'd'.repeat(64)}
|
${'cs2pr:1.2.3@sha256:' + 'd'.repeat(64)} | ${'linux'} | ${'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/download/1.2.3/cs2pr cs2pr "-V" sha256:' + 'd'.repeat(64)}
|
||||||
${'phive:0.15.3@sha512:' + 'c'.repeat(128)} | ${'darwin'} | ${'add_tool https://github.com/phar-io/phive/releases/download/0.15.3/phive-0.15.3.phar phive "status" sha512:' + 'c'.repeat(128)}
|
${'phive:0.15.3@sha512:' + 'c'.repeat(128)} | ${'darwin'} | ${'add_tool https://github.com/phar-io/phive/releases/download/0.15.3/phive-0.15.3.phar phive "status" sha512:' + 'c'.repeat(128)}
|
||||||
${'phinx:1.2.3@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "phinx" "Checksum verification is not supported for phinx"'}
|
${'phinx:1.2.3@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "phinx" "Checksum verification is not supported for phinx"'}
|
||||||
${'pecl@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "pecl" "Checksum verification is not supported for pecl"'}
|
${'pecl:1.2.3@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "pecl" "Checksum verification is not supported for pecl"'}
|
||||||
${'phpunit:9.5.0@sha256:invalid'} | ${'linux'} | ${'add_log "$cross" "phpunit" "Invalid sha256 checksum, expected 64 hexadecimal characters"'}
|
${'phpunit:9.5.0@sha256:invalid'} | ${'linux'} | ${'add_log "$cross" "phpunit" "Invalid sha256 checksum, expected 64 hexadecimal characters"'}
|
||||||
${'composer:2.9.8@SHA256:' + 'b'.repeat(64)} | ${'linux'} | ${'composer 2.9.8 sha256:' + 'b'.repeat(64)}
|
${'composer:2.9.8@SHA256:' + 'b'.repeat(64)} | ${'linux'} | ${'composer 2.9.8 sha256:' + 'b'.repeat(64)}
|
||||||
${'composer:2.9.8@sha384:' + 'b'.repeat(96)} | ${'linux'} | ${'add_log "$cross" "composer" "Unsupported checksum algorithm sha384, expected sha256 or sha512"'}
|
${'composer:2.9.8@sha384:' + 'b'.repeat(96)} | ${'linux'} | ${'add_log "$cross" "composer" "Unsupported checksum algorithm sha384, expected sha256 or sha512"'}
|
||||||
@@ -849,6 +850,44 @@ describe('Tools tests', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
describe.each(['linux', 'darwin', 'win32'])(
|
||||||
|
'Checksum version requirements on %s',
|
||||||
|
os => {
|
||||||
|
it.each([
|
||||||
|
'',
|
||||||
|
':latest',
|
||||||
|
':stable',
|
||||||
|
':preview',
|
||||||
|
':snapshot',
|
||||||
|
':2',
|
||||||
|
':2.x',
|
||||||
|
':2.9',
|
||||||
|
':2.9.x',
|
||||||
|
':^2.9.8'
|
||||||
|
])(
|
||||||
|
'rejects a checksum on a non-full version %s without an unpinned install',
|
||||||
|
async version => {
|
||||||
|
for (const tool of ['composer', 'phpunit']) {
|
||||||
|
const release = `${tool}${version}@sha256:${'a'.repeat(64)}`;
|
||||||
|
const data = await tools.getData(release, '8.4', os);
|
||||||
|
expect(data.error).toBe(
|
||||||
|
'Checksum pinning requires a full version, for example tool:1.2.3'
|
||||||
|
);
|
||||||
|
expect(data.url).toBe('');
|
||||||
|
const script = await tools.addTools(release, '8.4', os);
|
||||||
|
expect(script).toContain(data.error);
|
||||||
|
const installations = script
|
||||||
|
.split('\n')
|
||||||
|
.filter(line => /^add[-_]tool /i.test(line));
|
||||||
|
expect(
|
||||||
|
installations.some(line => new RegExp(` ${tool}( |$)`).test(line))
|
||||||
|
).toBe(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
it.each`
|
it.each`
|
||||||
type | tool_function | supported
|
type | tool_function | supported
|
||||||
${'phar'} | ${undefined} | ${true}
|
${'phar'} | ${undefined} | ${true}
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+14
-3
@@ -118,6 +118,12 @@ export function extractChecksum(release: string): {
|
|||||||
error: `Invalid ${algo} checksum, expected ${hash_length} hexadecimal characters`
|
error: `Invalid ${algo} checksum, expected ${hash_length} hexadecimal characters`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (!/^[^:]+:v?\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(release)) {
|
||||||
|
return {
|
||||||
|
release,
|
||||||
|
error: 'Checksum pinning requires a full version, for example tool:1.2.3'
|
||||||
|
};
|
||||||
|
}
|
||||||
return {release, checksum: `${algo}:${hash}`};
|
return {release, checksum: `${algo}:${hash}`};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,9 +314,13 @@ export async function filterList(tools_list: string[]): Promise<string[]> {
|
|||||||
const regex_any = /^composer($|:.*)/;
|
const regex_any = /^composer($|:.*)/;
|
||||||
const regex_valid =
|
const regex_valid =
|
||||||
/^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/;
|
/^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/;
|
||||||
const matches: string[] = tools_list.filter(tool =>
|
const matches: string[] = tools_list.filter(tool => {
|
||||||
regex_valid.test(extractChecksum(tool).release)
|
const parsed = extractChecksum(tool);
|
||||||
);
|
return (
|
||||||
|
regex_valid.test(parsed.release) ||
|
||||||
|
(regex_any.test(parsed.release) && parsed.error !== undefined)
|
||||||
|
);
|
||||||
|
});
|
||||||
let composer = 'composer';
|
let composer = 'composer';
|
||||||
tools_list = tools_list.filter(
|
tools_list = tools_list.filter(
|
||||||
tool => !regex_any.test(extractChecksum(tool).release)
|
tool => !regex_any.test(extractChecksum(tool).release)
|
||||||
@@ -721,6 +731,7 @@ export async function getData(
|
|||||||
data.checksum = checksum_data.checksum;
|
data.checksum = checksum_data.checksum;
|
||||||
data.error = checksum_data.error;
|
data.error = checksum_data.error;
|
||||||
data.release = await getRelease(release, data);
|
data.release = await getRelease(release, data);
|
||||||
|
if (data.error !== undefined) return data;
|
||||||
data.version = version
|
data.version = version
|
||||||
? await getVersion(version, data)
|
? await getVersion(version, data)
|
||||||
: await getLatestVersion(data);
|
: await getLatestVersion(data);
|
||||||
|
|||||||
Reference in New Issue
Block a user