Add validation of checksums

This commit is contained in:
Tom Hu
2021-04-15 22:08:27 -04:00
parent 6e56f7a5a6
commit 040839f579
4 changed files with 305 additions and 39 deletions

View File

@@ -5,6 +5,7 @@ const fs = require('fs');
const request = require('requestretry');
import buildExec from './buildExec';
import validateUploader from './validate';
let failCi;
try {
@@ -13,13 +14,19 @@ try {
maxAttempts: 10,
timeout: 3000,
url: 'https://codecov.io/bash',
}, (error, response, body) => {
const bashVersion = body.match('VERSION=\"(.*)\"');
conosole.log(bashVersion);
}, async (error, response, body) => {
const {execArgs, options, filepath, failCi} = buildExec();
try {
const isValid = await validateUploader(body);
if (!isValid) {
const failure = 'Codecov failure: ' +
'Bash script checksums do not match published values. ' +
'Please contact security@codecov.io immediately.';
core.setFailed(failure);
throw new Error(failure);
}
if (error && failCi) {
throw error;
} else if (error) {

28
src/validate.test.ts Normal file
View File

@@ -0,0 +1,28 @@
import validateUploader from './validate';
const request = require('requestretry');
const bashScript = (async () => {
try {
const script = await request({
json: false,
maxAttempts: 10,
timeout: 3000,
url: 'https://codecov.io/bash',
});
return script.body;
} catch (err) {
throw err;
}
});
test('validChecksums', async () => {
const valid = await validateUploader(await bashScript());
expect(valid).toBeTruthy();
});
test('invalidChecksums', async () => {
const script = await bashScript();
const valid = await validateUploader(script.substring(0, script.length - 1));
expect(valid).toBeFalsy();
});

58
src/validate.ts Normal file
View File

@@ -0,0 +1,58 @@
const crypto = require('crypto');
const core = require('@actions/core');
const request = require('requestretry');
const validateUploader = async (body) => {
const version = getVersion(body);
if (version === null) {
core.warning('Codecov could not identify the bash uploader version.');
return false;
}
for (const i of [1, 256, 512]) {
const publicChecksum = await retrieveChecksum(version, i);
const uploaderChecksum = calculateChecksum(body, i);
if (uploaderChecksum !== publicChecksum.trim()) {
core.warning(
`Codecov ${version} checksums for SHA1 failed to match.\n` +
`Public checksum: ${publicChecksum}` +
`Uploader checksum: ${uploaderChecksum}`,
);
return false;
}
}
return true;
};
const retrieveChecksum = async (version, encryption) => {
const url = `https://raw.githubusercontent.com/codecov/codecov-bash/${version}/SHA${encryption}SUM`;
try {
const response = await request({
maxAttempts: 10,
timeout: 3000,
url: url,
});
return response.body;
} catch (err) {
core.warning(
`Codecov could not retrieve checksum SHA${encryption} at ${url}`,
);
return false;
}
};
const calculateChecksum = (body, i) => {
const shasum = crypto.createHash(`sha${i}`);
shasum.update(body);
return `${shasum.digest('hex')} codecov`;
};
const getVersion = (body) => {
const regex = /VERSION="(.*)+"/g;
const match = regex.exec(body);
return match ? match[1] : null;
};
export default validateUploader;