Skip to content

Commit

Permalink
Add support for VirusTotal
Browse files Browse the repository at this point in the history
  • Loading branch information
nvdaes committed May 19, 2024
1 parent bfbb0b9 commit 0feee55
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 3 deletions.
66 changes: 63 additions & 3 deletions .github/workflows/checkAndSubmitAddonMetadata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ on:
issueTitle:
required: true
type: string

secrets:
virusTotalApiKey:
required: true
jobs:
getAddonId:
runs-on: windows-latest
Expand Down Expand Up @@ -225,11 +227,69 @@ jobs:
uses: peter-evans/close-issue@v3
with:
issue-number: ${{ inputs.issueNumber }}
codeQL-analysis:

virusTotal-analysis:
needs: createPullRequest
runs-on: windows-latest
strategy:
matrix:
python-version: [ 3.11 ]
permissions:
contents: write
pull-requests: write
issues: write
env:
API_KEY: ${{ secrets.virusTotalApiKey }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download add-on metadata
uses: actions/download-artifact@v4
with:
name: addonMetadata
- name: Install virusTotal
run: choco install vt-cli
- name: Set Virus Total analysis status
id: setVirusTotalAnalysisStatus
uses: actions/github-script@v7
with:
script: |
const setVirusTotalAnalysisStatus = require('./.github/workflows/virusTotalAnalysis.js')
setVirusTotalAnalysisStatus({core})
- name: Upload results
id: uploadResults
if: failure()
uses: actions/upload-artifact@v4
with:
name: VirusTotal
path: vt.json
overwrite: true
- name: Create pull request
id: cpr
if: failure()
uses: peter-evans/create-pull-request@v6
with:
add-paths: falsePositiveAddons.json
title: Add false positive add-on (${{ steps.setVirusTotalAnalysisStatus.outputs.addonId }})
branch: falsePositiveAddon${{ github.event.issue.number }}
commit-message: Add false positive add-on (${{ steps.setVirusTotalAnalysisStatus.outputs.addonId }})
body: "This add-on needs to be reviewed by NV Access due to VirusTotal analysis failure"
author: github-actions <github-actions@github.com>
delete-branch: true
- name: Warn if analysis fails
if: failure()
uses: peter-evans/create-or-update-comment@v4
with:
issue-number: ${{ inputs.issueNumber }}
body: |
VirusTotal has flagged this add-on as malicious.
You can open this link and [download artifacts containing the results of the analysis](${{ steps.uploadResults.outputs.artifact-url }}).
If you think this is a false positive or want more details, contact NV Access.
codeQL-analysis:
needs: [createPullRequest, virusTotal-analysis]
uses: ./.github/workflows/codeql-analysis.yml
mergeToMaster:
needs: [getAddonId, createPullRequest, codeQL-analysis]
needs: [getAddonId, createPullRequest, codeQL-analysis, virusTotal-analysis]
permissions:
contents: write
pull-requests: write
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/virusTotalAnalysis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = ({core}) => {
const fs = require('fs');
const { exec } = require('child_process');
const addonMetadataContents = fs.readFileSync('addonMetadata.json');
const addonMetadata = JSON.parse(addonMetadataContents);
const addonId = addonMetadata.addonId;
core.setOutput('addonId', addonId);
const sha256 = addonMetadata.sha256;
// const sha256 = '42335e36a209d39905414f0cbc71aa692338e3bf63efce8bc68d6949d2994ccd';
const falsePositiveAddonsContents = fs.readFileSync('falsePositiveAddons.json');
const falsePositiveAddonsData = JSON.parse(falsePositiveAddonsContents);
if (falsePositiveAddonsData[addonId] !== undefined && falsePositiveAddonsData[addonId].includes(sha256)) {
core.info('VirusTotal analysis skipped');
return;
}
exec(`vt file ${sha256} -k ${process.env.API_KEY} --format json`, (err, stdout, stderr) => {
console.log(stdout);
const vtData = JSON.parse(stdout);
fs.writeFileSync('vt.json', stdout);
const stats = vtData[0]["last_analysis_stats"];
const malicious = stats.malicious;
if (malicious === 0) {
core.info('VirusTotal analysis succeeded');
return;
}
if (falsePositiveAddonsData[addonId] === undefined) {
falsePositiveAddonsData[addonId] = [];
}
falsePositiveAddonsData[addonId].push(sha256);
stringified = JSON.stringify(falsePositiveAddonsData, null, 2);
fs.writeFileSync('falsePositiveAddons.json', stringified);
core.setFailed('VirusTotal analysis failed');
});
};
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ The add-on store includes the following security measures:
- The checksum allows NVDA to ensure that add-on releases are immutable.
- [Code scanning with CodeQL](https://docs.github.com/en/code-security/code-scanning/introduction-to-code-scanning/about-code-scanning-with-codeql) can detect vulnerabilities in Python and JavaScript code included in submitted add-ons.
- NV Access can manage [code scanning alerts](https://docs.github.com/en/code-security/code-scanning/managing-code-scanning-alerts/about-code-scanning-alerts), available from the Code scanning link from the [Security page](https://github.com/nvaccess/addon-datastore/security).
- [Virus Total CLI](https://virustotal.github.io/vt-cli) is used to scan submitted add-ons.
If malicious content is detected, the add-on will need to be manually approved by NV Access and won't be automatically included in the store.


### Human review process / code audit
Expand Down

0 comments on commit 0feee55

Please sign in to comment.