Receiving scan result

Scan results are published to the SNS Findings Topic. Learn more about the message format. Additionally, we tag the scanned object with the scan result. The following examples demonstrate how you can use the scan result in your applications.

Example: Generate a pre-signed URL for download if the file is tagged as clean (#)

The following example queries the object’s tags and extracts the scan result before generating a pre-signed URL for download.

JavaScript (#)

Run npm i aws-sdk to install the required dependency.

const AWS = require('aws-sdk');
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });

function getSignedUrl (bucket, key, cb) {
  s3.getObjectTagging({
    Bucket: bucket,
    Key: key
  }, (err, data) => {
    if (err) {
      cb(err);
    } else {
      const tag = data.TagSet.find(tag => tag.Key === 'bucketav');
      if (tag !== undefined && tag.Value === 'clean') {
        s3.getSignedUrl('getObject', {
          Bucket: bucket,
          Key: key
        }, (err, signedUrl) => {
          if (err) {
            cb(err);
          } else {
            cb(null, signedUrl);
          }
        });
      } else {
        cb(null, null);
      }
    }
  });
}

getSignedUrl('your-bucket', 'path/to/file.pdf', (err, signedUrl) => {
  if (err) {
    console.error('something went wrong', err);
  } else {
    if (signedUrl === null) {
      console.log('download not possible (file infected, unscannable, or not yet scanned)');
    } else {
      console.log(signedUrl);
    }
  }
});

GitHub: https://github.com/widdix/bucketav-developer-examples/blob/main/javascript/pre-signed-download-based-on-tag.js

Python (#)

Run pip install boto3 to install the required dependency.

import boto3

s3 = boto3.client('s3')

def get_signed_url(bucket, key):
    response = s3.get_object_tagging(
        Bucket=bucket,
        Key=key
    )

    tags = response['TagSet']
    tag = next((t for t in tags if t['Key'] == 'bucketav'), None)

    if tag is not None and tag['Value'] == 'clean':
        signed_url = s3.generate_presigned_url(
            'get_object',
            Params={
                'Bucket': bucket,
                'Key': key
            }
        )
        return signed_url
    else:
        return None

signed_url = get_signed_url('your-bucket', 'path/to/file.pdf')

if signed_url is None:
    print('Download not possible (file infected, unscannable, or not yet scanned)')
else:
    print(signed_url)

GitHub: https://github.com/widdix/bucketav-developer-examples/blob/main/python/pre-signed-download-based-on-tag.py

Example: Subscribe to Findings Topic and store results in DynamoDB (#)

The following example:

  1. Subscribes to the Findings Topic
  2. Stores scan results in DynamoDB
  3. Queries DynamoDB and extracts the scan result before generating a pre-signed URL for download.

Please find the example on GitHub: https://github.com/widdix/bucketav-developer-examples/tree/main/javascript/subscribe-to-findings-topic

SNS message format (#)

The SNS topic name is prefixed by the CloudFormation stack name you defined during setup (if you followed the docs, the prefix is bucketav).

If the subscription protocol is set to email, the body contains a human-readable string. Otherwise, the body is formatted in JSON with the following keys/structure.

JSON payloads require bucketAV powered by ClamAV® version >= 2.1.0 or bucketAV powered by Sophos® version >= 2.0.0. To update to the latest version, follow the Update Guide.

  • bucket (string): The bucket name.
  • key (string): The object key.
  • version (string, optional): If versioning is turned on, the object version (requires bucketAV powered by ClamAV® version >= 2.3.0 or bucketAV powered by Sophos® version >= 2.0.0).
  • size (number): The object size in bytes (requires bucketAV powered by ClamAV® version >= 2.13.0 or bucketAV powered by Sophos® version >= 2.2.0).
  • status (string (clean, infected, no)): The scan result.
  • action (string (delete, tag, no)): The action that was taken.
  • finding (string, optional): For infected files, the type of virus/malware that was detected.
  • trace_id (string, optional): ID to trace custom scan jobs (requires bucketAV powered by ClamAV® version >= 2.9.0 or bucketAV powered by Sophos® version >= 2.0.0).
  • custom_data (string, optional): Custom data defined when submitting a custom scan job (requires bucketAV powered by ClamAV® version >= 2.9.0 or bucketAV powered by Sophos® version >= 2.0.0).
{
  "bucket": "testbucket",
  "key": "bucketav/test/file.pdf",
  "version": "optional_qAKVCwsELNe_pDHtdIIzX_jRJAcKVQaG",
  "status": "infected",
  "action": "delete",
  "finding": "optional_TestWorm",
  "trace_id": "1234567",  
  "custom_data": "..."
}

The following message attributes are part of every message and can be used for message filtering:

SNS attribute values must not contain surrogate characters (e.g., some emojis). Therefore, we replace them with the # character. Inspect the JSON body to get the raw data.

  • bucket (string): The bucket name.
  • key (string): The object key
  • version (string, optional): If versioning is turned on, the object version.
  • size (number): The object size in bytes (requires bucketAV powered by ClamAV® version >= 2.13.0 or bucketAV powered by Sophos® version >= 2.2.0).
  • status (string (clean, infected, no)): The scan result.
  • action (string (delete, tag, no)): The action that was taken.
  • finding (string, optional): For infected files, the type of virus/malware that was detected (requires bucketAV powered by ClamAV® version >= 1.7.0 or bucketAV powered by Sophos® version >= 2.0.0).
  • trace_id (string, optiona): ID to trace custom scan jobs (requires bucketAV powered by ClamAV® version >= 2.9.0 or bucketAV powered by Sophos® version >= 2.0.0).

Need more help?

Write us, and we'll get back to you as soon as we can.

Send us an email