Skip to content
This repository has been archived by the owner on Sep 19, 2023. It is now read-only.

Commit

Permalink
Merge pull request #31 from Yoshiin/yoshin/add-mime-type-filter
Browse files Browse the repository at this point in the history
Adding a mime type filter
  • Loading branch information
michaelkaye authored Dec 21, 2018
2 parents 1f258fe + 0e07830 commit 267c79f
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 838 deletions.
6 changes: 6 additions & 0 deletions config/default.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,9 @@ middleware:
# the unpickled key will be used to decrypt encrypted_body
# requests.
picklePath: 'av_pickled_decryption.key'

# Optional. A list of accepted mime type.
#acceptedMimeType:
# - 'image/jpeg'
# - 'image/jpg'
# - 'image/png'
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
"start": "node src/index.js"
},
"dependencies": {
"express": "^4.16.3",
"cors": "^2.8.4",
"express": "^4.16.3",
"express-validation": "^1.0.2",
"file-type": "^10.5.0",
"joi": "^13.3.0",
"js-yaml": "^3.12.0",
"olm": "https://matrix.org/packages/npm/olm/olm-2.3.0.tgz",
Expand Down
1 change: 1 addition & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const configSchema = Joi.object().keys({
picklePath: Joi.string().required(),
}),
}),
acceptedMimeType: Joi.array(),
});

// Exported alongside mechanism to load particular configuarion
Expand Down
29 changes: 23 additions & 6 deletions src/reporting.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ const decryptFile = require('./decrypt-file.js');

const crypto = require('crypto');

const { getConfig } = require('./config.js');
const fileType = require('file-type');

// Generate a bas64 SHA 256 hash of the input string
function base64sha256(s) {
const hash = crypto.createHash('sha256');
Expand Down Expand Up @@ -258,24 +261,38 @@ async function generateReport(console, httpUrl, matrixFile, filePath, tempDir, s
return reportCache[reportHash];
}

let mimetypeArray = getConfig().acceptedMimeType;
// Always make a decryptedFile on disk
let decryptedFilePath = path.join(tempDir, 'unsafeDownloadedDecryptedFile');

if (matrixFile && matrixFile.key) {
console.info(`Decrypting ${filePath}, writing to ${decryptedFilePath}`);

console.info(`FileType: ${matrixFile.mimetype}`);
if (mimetypeArray && !mimetypeArray.includes(matrixFile.mimetype)) {
return {clean: false, info: 'File type not supported'};
}
try {
decryptFile(filePath, decryptedFilePath, matrixFile);
} catch (err) {
console.error(err);
throw new ClientError(400, 'Failed to decrypt file', 'MCS_MEDIA_FAILED_TO_DECRYPT');
}
} else {
try {
fs.copyFileSync(filePath, decryptedFilePath);
} catch (err) {
console.error(err);
throw new ClientError(400, 'Failed to copy file for decryption', 'MCS_MEDIA_FAILED_TO_DECRYPT');
let fileData = fs.readFileSync(filePath);
let type = fileType(fileData);
if (mimetypeArray) {
if (type === null) {
return {clean: false, info: 'File type not supported'};
} else if (!mimetypeArray.includes(type.mime)) {
console.info(`FileType: ${type.mime}`);
return {clean: false, info: 'File type not supported'};
}
try {
fs.copyFileSync(filePath, decryptedFilePath);
} catch (err) {
console.error(err);
throw new ClientError(400, 'Failed to copy file for decryption', 'MCS_MEDIA_FAILED_TO_DECRYPT');
}
}
}

Expand Down
40 changes: 40 additions & 0 deletions test/handlers-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,46 @@ describe('handlers', () => {
assert(response.body.clean, true);
});
});

it('responds with a bad scan report if the mimetype is not accepted in the configuration file', async () => {
setConfig({
scan: {
baseUrl: "https://matrix.org",
tempDirectory: "/tmp",
script: "exit 0"
},
altRemovalCmd: 'rm',
acceptedMimeType: ['image/jpg']
});
const app = await createApp();
return request(app)
.get('/_matrix/media_proxy/unstable/scan/matrix.org/EawFuailhYTuSPSGDGsNFigt')
.expect('Content-Type', /json/)
.expect(200)
.then(response => {
assert.strictEqual(response.body.clean, false);
});
});

it('responds with a scan report if the mimetype is accepted in the configuration file', async () => {
setConfig({
scan: {
baseUrl: "https://matrix.org",
tempDirectory: "/tmp",
script: "exit 0"
},
altRemovalCmd: 'rm',
acceptedMimeType: ['image/png']
});
const app = await createApp();
return request(app)
.get('/_matrix/media_proxy/unstable/scan/matrix.org/EawFuailhYTuSPSGDGsNFigt')
.expect('Content-Type', /json/)
.expect(200)
.then(response => {
assert(response.body.clean, true);
});
});
});

describe('GET /_matrix/media_proxy/unstable/thumbnail/matrix.org/EawFuailhYTuSPSGDGsNFigt?width=100&height=100&method=scale', () => {
Expand Down
Loading

0 comments on commit 267c79f

Please sign in to comment.