Repository: tenable/terrascan (language: python)

Issue:
Add Support For ECR



Discussion / hints:

Fix patch:
diff --git a/README.md b/README.md
index 857c3b04c..e27a64b52 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,7 @@ Terrascan is a static code analyzer for Infrastructure as Code. Terrascan allows
 * Scanning of Kubernetes (JSON/YAML), Helm v3, and Kustomize v3
 * Scanning of Dockerfiles
 * Support for AWS, Azure, GCP, Kubernetes, Dockerfiles, and GitHub
+* Integrates with docker image vulnerability scanning for AWS, Azure, GCP container registries.
 
 ## Quick Start
 
@@ -121,6 +122,17 @@ By default, Terrascan downloads policies from Terrascan repositories while scann
 
 Note: The scan command will implicitly run the initialization process if there are no policies found.
 
+## Docker Image Vulnerabilities
+You can use the `--find-vuln` flag to collect vulnerabilities as reported in its registry as part of Terrascan's output. Currently Terrascan supports Elastic Container Registry (ECR), Azure Container Registry, Google Container Registry, and Google Artifact Registry.
+
+The `--find-vuln` flag can be used when scanning IaC files as follows:
+
+```
+$ terrascan scan -i <IaC provider> --find-vuln
+```
+
+For more information and explanation of how to setup your environment to authenticate with the registrie's APIs see the [usage](https://runterrascan.io/docs/usage/command_line_mode/) documentation.
+
 ## Customizing scans
 
 By default, Terrascan scans your entire configuration against all policies. However, Terrascan supports granular configuration of policies and resources.
diff --git a/docs/usage/command_line_mode.md b/docs/usage/command_line_mode.md
index 0694bafd4..bb5c66875 100644
--- a/docs/usage/command_line_mode.md
+++ b/docs/usage/command_line_mode.md
@@ -63,11 +63,12 @@ $ terrascan scan
 ```
 
 The `scan` command supports flags to configure the following:
-- Specify a directory to be scanned.
-- Specify a particular IaC file to be scanned.
+- Specify a directory to be scanned
+- Specify a particular IaC file to be scanned
 - Configure IaC provider type
 - Directory path to policies
-- Specify policy type.
+- Specify policy type
+- Retrieve vulnerability scanning results from docker images referenced in IaC
 
 The full list of flags for the scan command can be found by typing
 `terrascan scan -h`
@@ -158,6 +159,7 @@ $ terrascan scan -i kustomize
 This command looks for a `kustomization.yaml` file in the current directory and scans rendered .yaml or .yml template files.
 
 A specific directory to scan can be specified using the `-d` flag. The Kustomize IaC provider does not support scanning of individual files using the `-f` flag.
+
 ### Scanning a Dockerfile
 
 A Dockerfile can be scanned by specifying "docker" on the -i flag as follows:
@@ -170,6 +172,44 @@ This command looks for a `Dockerfile` in the current directory and scans that fi
 
 A specific directory to scan can be specified using the `-d` flag. With the `-d` flag, it will check for all the docker files (named as `Dockerfile`) in the provided directory recursively. A specific dockerfile can be scanned using `-f` flag by providing a path to the file.
 
+### Retrieve Docker Image Vulnerabilities
+
+Terrascan can display vulnerabilities for Docker images present in the IaC files being scanned by specifying the `--find-vuln` flag along with the scan command as follows:
+
+```
+$ terrascan scan -i <IaC Provider> --find-vuln
+```
+
+This command looks for all the Docker images present in the IaC files being scanned and retrieves any vulnerabilities as reported by it's container registry. Supported container registries include: AWS Elastic Container Registry (ECR), Azure Container Registry, Google Container Registry, and Google Artifact Registry.
+
+The following environment variables are required when connecting to the container registries:
+
+#### AWS Elastic Container Registry (ECR)
+
+ECR requires your environment to be configured similar to the requirements of AWS's SDK. For example, the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION` environment variables can be set when connecting to AWS using API keys for an AWS user. More information [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html).
+
+#### Google Container Registry and Artifact Registry
+
+Terrascan requires a service account with access to the Container Analysis and Container Registry permissions. The `GOOGLE_APPLICATION_CREDENTIALS` environment variable can be set to the path of the service account's key when scanning. More information about GCP authentication available [here](https://cloud.google.com/docs/authentication/getting-started).
+
+#### Azure Container Registry
+
+When integrating vulnerability results from Azure, Terrascan requires the `AZURE_AUTH_LOCATION`, and `AZURE_ACR_PASSWORD` environment variables.
+
+The `AZURE_AUTH_LOCATION` should contain the path to your azure authentication json. You can generate this as follows:
+
+ ``` Bash
+ az ad sp create-for-rbac --sdk-auth > azure.auth
+ ```
+
+After generating the file, set the `azure.auth` file path as the `AZURE_AUTH_LOCATION` environment variable. More information about using file based authentication for the Azure SDK available [here](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-file-based-authentication).
+
+Terrascan also requires the password to the registry set into the `AZURE_ACR_PASSWORD` environment variable. This can be fetched using the az cli as follows:
+
+``` Bash
+az acr credential show --name RegistryName
+```
+
 ### Resource Config
 While scanning a IaC, Terrascan loads all the IaC files, creates a list of resource configs and then processes this list to report violations. For debugging purposes, you can print this resource configs list as an output by using the `--config-only` flag to the `terrascan scan` command.
 
@@ -216,6 +256,7 @@ aws_ecr_repository:
 | |use-colours |Configure the color for output (**auto**, t, f) |
 |--non-recursive |Use this for non recursive directories and modules scan | By default directory is scanned recursively, if this flag is used then only provided root directory will be scanned|
 |--use-terraform-cache |Use this to refer terraform remote modules from terraform init cache rather than downloading | By default remote module will be downloaded in temporary directory. If this flag is set then modules will be refered from terraform init cache if module is not present in terraform init cache it will be downloaded. Directory will be scanned non recurively if this flag is used.(applicable only with terraform IaC provider)|
+| --find-vuln | find vulnerbilities | Use this to fetch vulnerabilities identified on the registry for docker images present in IaC the files scanned |
 | -v | verbose | Displays violations with all details |
 
 | Global flags | Description | Options |
@@ -242,6 +283,7 @@ Usage:
 Flags:
      --categories strings        list of categories of violations to be reported by terrascan (example: --categories="category1,category2")
       --config-only               will output resource config (should only be used for debugging purposes)
+      --find-vuln                 fetches vulnerabilities identified in Docker images
   -h, --help                      help for scan
   -d, --iac-dir string            path to a directory containing one or more IaC files (default ".")
   -f, --iac-file string           path to a single IaC file
diff --git a/go.mod b/go.mod
index 3c9055077..20dc59f13 100644
--- a/go.mod
+++ b/go.mod
@@ -10,8 +10,14 @@ replace (
 )
 
 require (
+	cloud.google.com/go v0.65.0
+	github.com/Azure/azure-sdk-for-go v56.2.0+incompatible
+	github.com/Azure/go-autorest/autorest v0.11.18
+	github.com/Azure/go-autorest/autorest/azure/auth v0.4.2
 	github.com/BurntSushi/toml v0.4.1 // indirect
+	github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible
 	github.com/VerbalExpressions/GoVerbalExpressions v0.0.0-20200410162751-4d76a1099a6e
+	github.com/aws/aws-sdk-go v1.37.0
 	github.com/aws/aws-sdk-go-v2/config v1.5.0
 	github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.3.2
 	github.com/aws/aws-sdk-go-v2/service/s3 v1.11.1
@@ -19,6 +25,7 @@ require (
 	github.com/awslabs/goformation/v4 v4.19.1
 	github.com/ghodss/yaml v1.0.0
 	github.com/go-errors/errors v1.0.1
+	github.com/google/go-containerregistry v0.1.2
 	github.com/google/uuid v1.2.0
 	github.com/gorilla/handlers v1.5.1
 	github.com/gorilla/mux v1.8.0
@@ -49,6 +56,8 @@ require (
 	go.uber.org/zap v1.16.0
 	golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069
 	golang.org/x/tools v0.1.5 // indirect
+	google.golang.org/api v0.34.0
+	google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a
 	gopkg.in/src-d/go-git.v4 v4.13.1
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
 	helm.sh/helm/v3 v3.6.1
diff --git a/go.sum b/go.sum
index 43049a347..5c41b4524 100644
--- a/go.sum
+++ b/go.sum
@@ -67,6 +67,8 @@ github.com/Azure/azure-sdk-for-go v45.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
 github.com/Azure/azure-sdk-for-go v47.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v51.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-sdk-for-go v52.5.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
+github.com/Azure/azure-sdk-for-go v56.2.0+incompatible h1:2GrG1JkTSMqLquy1pqVsjeRJhNtZLjss2+rx8ogZXx4=
+github.com/Azure/azure-sdk-for-go v56.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
 github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0=
 github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@@ -76,6 +78,7 @@ github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW
 github.com/Azure/go-autorest v10.15.5+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest v14.1.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
+github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
 github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
 github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
 github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
@@ -83,6 +86,7 @@ github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdA
 github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
 github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
 github.com/Azure/go-autorest/autorest v0.11.10/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
+github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
 github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
 github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
 github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
@@ -93,18 +97,23 @@ github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQW
 github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
 github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
 github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
+github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
 github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
+github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk=
 github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
 github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
 github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s=
+github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY=
 github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
 github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
 github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
+github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
 github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
 github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
 github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
 github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
 github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
+github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
 github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
 github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc=
 github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA=
@@ -114,11 +123,14 @@ github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcP
 github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8=
 github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI=
 github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
+github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
 github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
 github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
 github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
+github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
 github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
 github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
+github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
 github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
@@ -132,6 +144,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q
 github.com/Djarvur/go-err113 v0.0.0-20200410182137-af658d038157/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
 github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
 github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
+github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible h1:juIaKLLVhqzP55d8x4cSVgwyQv76Z55/fRv/UBr2KkQ=
+github.com/GoogleCloudPlatform/docker-credential-gcr v2.0.5+incompatible/go.mod h1:BB1eHdMLYEFuFdBlRMb0N7YGVdM5s6Pt0njxgvfbGGs=
 github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
@@ -411,11 +425,13 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
+github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
 github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
 github.com/docker/cli v0.0.0-20190925022749-754388324470/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 github.com/docker/cli v20.10.0-beta1.0.20201029214301-1d20b15adc38+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
+github.com/docker/cli v20.10.5+incompatible h1:bjflayQbWg+xOkF2WPEAOi4Y7zWhR7ptoPhV/VqLVDE=
 github.com/docker/cli v20.10.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
 github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
@@ -431,6 +447,7 @@ github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompati
 github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible h1:J2OhsbfqoBRRT048iD/tqXBvEQWQATQ8vew6LqQmDSU=
 github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
 github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
 github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
 github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
@@ -481,6 +498,7 @@ github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
 github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
 github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
@@ -635,6 +653,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
 github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
 github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
 github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
 github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
 github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v0.0.0-20181025225059-d3de96c4c28e/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
@@ -692,6 +711,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE=
+github.com/google/go-containerregistry v0.1.2 h1:YjFNKqxzWUVZND8d4ItF9wuYlE75WQfECE7yKX/Nu3o=
 github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4=
 github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
 github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
@@ -1304,6 +1324,7 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
 github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
@@ -1658,6 +1679,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -2030,8 +2052,10 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
 gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
+gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
 gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
 grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
 helm.sh/helm/v3 v3.6.1 h1:TQ6q4pAatXr7qh2fbLcb0oNd0I3J7kv26oo5cExKTtc=
diff --git a/pkg/cli/run.go b/pkg/cli/run.go
index e26bbd633..78b1a4c0f 100644
--- a/pkg/cli/run.go
+++ b/pkg/cli/run.go
@@ -99,6 +99,9 @@ type ScanOptions struct {
 
 	// useTerraformCache provides ability to use terraform init local cache for modules rather than downloading them.
 	useTerraformCache bool
+
+	// FindVulnerabilities gives option to scan container images for vulnerabilities
+	findVulnerabilities bool
 }
 
 // NewScanOptions returns a new pointer to ScanOptions
@@ -184,7 +187,7 @@ func (s *ScanOptions) Run() error {
 
 	// create a new runtime executor for processing IaC
 	executor, err := runtime.NewExecutor(s.iacType, s.iacVersion, s.policyType,
-		s.iacFilePath, s.iacDirPath, s.policyPath, s.scanRules, s.skipRules, s.categories, s.severity, s.nonRecursive, s.useTerraformCache)
+		s.iacFilePath, s.iacDirPath, s.policyPath, s.scanRules, s.skipRules, s.categories, s.severity, s.nonRecursive, s.useTerraformCache, s.findVulnerabilities)
 	if err != nil {
 		return err
 	}
diff --git a/pkg/cli/scan.go b/pkg/cli/scan.go
index 38a55f006..f2a71ac55 100644
--- a/pkg/cli/scan.go
+++ b/pkg/cli/scan.go
@@ -73,5 +73,6 @@ func init() {
 	scanCmd.Flags().BoolVarP(&scanOptions.showPassedRules, "show-passed", "", false, "display passed rules, along with violations")
 	scanCmd.Flags().BoolVarP(&scanOptions.nonRecursive, "non-recursive", "", false, "do not scan directories and modules recursively")
 	scanCmd.Flags().BoolVarP(&scanOptions.useTerraformCache, "use-terraform-cache", "", false, "use terraform init cache for remote modules (when used directory scan will be non recursive, flag applicable only with terraform IaC provider)")
+	scanCmd.Flags().BoolVarP(&scanOptions.findVulnerabilities, "find-vuln", "", false, "fetches vulnerabilities identified in Docker images")
 	RegisterCommand(rootCmd, scanCmd)
 }
diff --git a/pkg/http-server/file-scan.go b/pkg/http-server/file-scan.go
index d44bfc420..d061cf344 100644
--- a/pkg/http-server/file-scan.go
+++ b/pkg/http-server/file-scan.go
@@ -40,14 +40,15 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) {
 	// get url params
 	params := mux.Vars(r)
 	var (
-		iacType    = params["iac"]
-		iacVersion = params["iacVersion"]
-		cloudType  = strings.Split(params["cloud"], ",")
-		scanRules  = []string{}
-		skipRules  = []string{}
-		configOnly = false
-		showPassed = false
-		categories = []string{}
+		iacType             = params["iac"]
+		iacVersion          = params["iacVersion"]
+		cloudType           = strings.Split(params["cloud"], ",")
+		scanRules           = []string{}
+		skipRules           = []string{}
+		configOnly          = false
+		showPassed          = false
+		findVulnerabilities = false
+		categories          = []string{}
 	)
 
 	// parse multipart form, 10 << 20 specifies maximum upload of 10 MB files
@@ -108,6 +109,17 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) {
 	// severity is the minimum severity level of violations that the user want to get informed about: low, medium or high
 	severity := r.FormValue("severity")
 
+	findVulnerabilitiesValue := r.FormValue("find_vulnerabilities")
+	if findVulnerabilitiesValue != "" {
+		findVulnerabilities, err = strconv.ParseBool(findVulnerabilitiesValue)
+		if err != nil {
+			errMsg := fmt.Sprintf("error while reading 'find_vulnerabilities' value. error: '%v'", err)
+			zap.S().Error(errMsg)
+			apiErrorResponse(w, errMsg, http.StatusBadRequest)
+			return
+		}
+	}
+
 	// read config_only from the form data
 	configOnlyValue := r.FormValue("config_only")
 	if configOnlyValue != "" {
@@ -152,10 +164,10 @@ func (g *APIHandler) scanFile(w http.ResponseWriter, r *http.Request) {
 	var executor *runtime.Executor
 	if g.test {
 		executor, err = runtime.NewExecutor(iacType, iacVersion, cloudType,
-			tempFile.Name(), "", []string{"./testdata/testpolicies"}, scanRules, skipRules, categories, severity, false, false)
+			tempFile.Name(), "", []string{"./testdata/testpolicies"}, scanRules, skipRules, categories, severity, false, false, false)
 	} else {
 		executor, err = runtime.NewExecutor(iacType, iacVersion, cloudType,
-			tempFile.Name(), "", getPolicyPathFromConfig(), scanRules, skipRules, categories, severity, false, false)
+			tempFile.Name(), "", getPolicyPathFromConfig(), scanRules, skipRules, categories, severity, false, false, findVulnerabilities)
 	}
 	if err != nil {
 		zap.S().Error(err)
diff --git a/pkg/http-server/remote-repo.go b/pkg/http-server/remote-repo.go
index 1909158e0..0b833b568 100644
--- a/pkg/http-server/remote-repo.go
+++ b/pkg/http-server/remote-repo.go
@@ -35,16 +35,17 @@ import (
 
 // scanRemoteRepoReq contains request body for remote repository scanning
 type scanRemoteRepoReq struct {
-	RemoteType   string   `json:"remote_type"`
-	RemoteURL    string   `json:"remote_url"`
-	ConfigOnly   bool     `json:"config_only"`
-	ScanRules    []string `json:"scan_rules"`
-	SkipRules    []string `json:"skip_rules"`
-	Categories   []string `json:"categories"`
-	Severity     string   `json:"severity"`
-	ShowPassed   bool     `json:"show_passed"`
-	NonRecursive bool     `json:"non_recursive"`
-	d            downloader.Downloader
+	RemoteType          string   `json:"remote_type"`
+	RemoteURL           string   `json:"remote_url"`
+	ConfigOnly          bool     `json:"config_only"`
+	ScanRules           []string `json:"scan_rules"`
+	SkipRules           []string `json:"skip_rules"`
+	Categories          []string `json:"categories"`
+	Severity            string   `json:"severity"`
+	ShowPassed          bool     `json:"show_passed"`
+	NonRecursive        bool     `json:"non_recursive"`
+	FindVulnerabilities bool     `json:"find_vulnerabilities"`
+	d                   downloader.Downloader
 }
 
 // scanRemoteRepo downloads the remote Iac repository and scans it for
@@ -128,7 +129,7 @@ func (s *scanRemoteRepoReq) ScanRemoteRepo(iacType, iacVersion string, cloudType
 
 	// create a new runtime executor for scanning the remote repo
 	executor, err := runtime.NewExecutor(iacType, iacVersion, cloudType,
-		"", iacDirPath, policyPath, s.ScanRules, s.SkipRules, s.Categories, s.Severity, s.NonRecursive, false)
+		"", iacDirPath, policyPath, s.ScanRules, s.SkipRules, s.Categories, s.Severity, s.NonRecursive, false, s.FindVulnerabilities)
 	if err != nil {
 		zap.S().Error(err)
 		return output, isAdmissionDenied, err
diff --git a/pkg/iac-providers/kubernetes/v1/extract-images.go b/pkg/iac-providers/kubernetes/v1/extract-images.go
index d28ef3923..a2fe94f26 100644
--- a/pkg/iac-providers/kubernetes/v1/extract-images.go
+++ b/pkg/iac-providers/kubernetes/v1/extract-images.go
@@ -30,9 +30,9 @@ import (
 	k8scorev1 "k8s.io/api/core/v1"
 )
 
-func (k *K8sV1) extractContainerImages(kind string, doc *utils.IacDocument) ([]output.ContainerNameAndImage, []output.ContainerNameAndImage, error) {
-	var containerImages = make([]output.ContainerNameAndImage, 0)
-	var initContainerImages = make([]output.ContainerNameAndImage, 0)
+func (k *K8sV1) extractContainerImages(kind string, doc *utils.IacDocument) ([]output.ContainerDetails, []output.ContainerDetails, error) {
+	var containerImages = make([]output.ContainerDetails, 0)
+	var initContainerImages = make([]output.ContainerDetails, 0)
 	var data []byte
 	var err error
 
@@ -141,9 +141,9 @@ func (k *K8sV1) extractContainerImages(kind string, doc *utils.IacDocument) ([]o
 }
 
 //readContainers prepares list of containers and init containers from k8scorev1.Container object
-func readContainers(containers []k8scorev1.Container) (containerImages []output.ContainerNameAndImage) {
+func readContainers(containers []k8scorev1.Container) (containerImages []output.ContainerDetails) {
 	for _, container := range containers {
-		containerImages = append(containerImages, output.ContainerNameAndImage{Name: container.Name, Image: container.Image})
+		containerImages = append(containerImages, output.ContainerDetails{Name: container.Name, Image: container.Image})
 	}
 	return
 }
diff --git a/pkg/iac-providers/kubernetes/v1/normalize.go b/pkg/iac-providers/kubernetes/v1/normalize.go
index 78b5f9f02..6a23fb75f 100644
--- a/pkg/iac-providers/kubernetes/v1/normalize.go
+++ b/pkg/iac-providers/kubernetes/v1/normalize.go
@@ -19,6 +19,7 @@ package k8sv1
 import (
 	"encoding/json"
 	"fmt"
+
 	"github.com/accurics/terrascan/pkg/iac-providers/output"
 	"github.com/accurics/terrascan/pkg/utils"
 	yamltojson "github.com/ghodss/yaml"
@@ -111,9 +112,9 @@ func (k *K8sV1) Normalize(doc *utils.IacDocument) (*output.ResourceConfig, error
 	}
 
 	var resourceConfig output.ResourceConfig
-	resourceConfig.ContainerImages = make([]output.ContainerNameAndImage, 0)
-	resourceConfig.InitContainerImages = make([]output.ContainerNameAndImage, 0)
-	var containerImages, initContainerImages []output.ContainerNameAndImage
+	resourceConfig.ContainerImages = make([]output.ContainerDetails, 0)
+	resourceConfig.InitContainerImages = make([]output.ContainerDetails, 0)
+	var containerImages, initContainerImages []output.ContainerDetails
 	resourceConfig.Type = k.getNormalizedName(resource.Kind)
 
 	switch resource.Kind {
diff --git a/pkg/iac-providers/output/types.go b/pkg/iac-providers/output/types.go
index 5ca7715a3..f4af90ea9 100644
--- a/pkg/iac-providers/output/types.go
+++ b/pkg/iac-providers/output/types.go
@@ -35,17 +35,18 @@ type ResourceConfig struct {
 	// SkipRules will hold the rules to be skipped for the resource.
 	// Each iac provider should append the rules to be skipped for a resource,
 	// while extracting resource from the iac files
-	SkipRules           []SkipRule              `json:"skip_rules" yaml:"skip_rules"`
-	MaxSeverity         string                  `json:"max_severity"`
-	MinSeverity         string                  `json:"min_severity"`
-	ContainerImages     []ContainerNameAndImage `json:"container_images,omitempty"`
-	InitContainerImages []ContainerNameAndImage `json:"init_container_images,omitempty"`
+	SkipRules           []SkipRule         `json:"skip_rules" yaml:"skip_rules"`
+	MaxSeverity         string             `json:"max_severity"`
+	MinSeverity         string             `json:"min_severity"`
+	ContainerImages     []ContainerDetails `json:"container_images,omitempty"`
+	InitContainerImages []ContainerDetails `json:"init_container_images,omitempty"`
 }
 
-// ContainerNameAndImage container name and image
-type ContainerNameAndImage struct {
-	Name  string `json:"name"`
-	Image string `json:"image"`
+// ContainerDetails holds information about container name, image and vulberabilities
+type ContainerDetails struct {
+	Name            string          `json:"name"`
+	Image           string          `json:"image"`
+	Vulnerabilities []Vulnerability `json:"vulnerabilities"`
 }
 
 // SkipRule struct will hold the skipped rule and any comment for the skipped rule
diff --git a/pkg/iac-providers/output/vulnerability.go b/pkg/iac-providers/output/vulnerability.go
new file mode 100644
index 000000000..de7313450
--- /dev/null
+++ b/pkg/iac-providers/output/vulnerability.go
@@ -0,0 +1,251 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package output
+
+import (
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/aws/aws-sdk-go/service/ecr"
+	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
+)
+
+const (
+	ecrPackageName    = "package_name"
+	ecrPackageVersion = "package_version"
+	ecrCvss           = "CVSS"
+	ecrCvssVector     = "VECTOR"
+	ecrCvssScore      = "SCORE"
+	nvd               = "nvd"
+	primaryURL        = "https://cve.mitre.org/cgi-bin/cvename.cgi?name="
+)
+
+// VendorCVSS holds cvss scoring vector for different vendors
+type VendorCVSS map[string]CVSS
+
+// Vulnerability holds vulnerability details of image
+type Vulnerability struct {
+	Target           string     `json:"target"`
+	Type             string     `json:"type,omitempty"`
+	VulnerabilityID  string     `json:"vulnerability_id,omitempty"`
+	PkgName          string     `json:"pkg_name,omitempty"`
+	InstalledVersion string     `json:"installed_version,omitempty"`
+	FixedVersion     string     `json:"fixed_version,omitempty"`
+	SeveritySource   string     `json:"severity_source,omitempty"`
+	PrimaryURL       string     `json:"primary_url,omitempty"`
+	Title            string     `json:"title,omitempty"`
+	Description      string     `json:"description,omitempty"`
+	Severity         string     `json:"severity,omitempty"`
+	CweIDs           []string   `json:"cwe_ids,omitempty"`
+	CVSS             VendorCVSS `json:"cvss,omitempty"`
+	References       []string   `json:"references,omitempty"`
+	PublishedDate    *time.Time `json:"published_date,omitempty"`
+	LastModifiedDate *time.Time `json:"lastModified_date,omitempty"`
+}
+
+// CVSS holds score and vector details
+type CVSS struct {
+	V2Vector string  `json:"v2_vector,omitempty"`
+	V3Vector string  `json:"v3_vector,omitempty"`
+	V2Score  float64 `json:"v2_score,omitempty"`
+	V3Score  float64 `json:"v3_score,omitempty"`
+}
+
+//ACRResponse holds response from ACR api call
+type ACRResponse struct {
+	Properties ACRVulnerabilityConfig `json:"properties"`
+}
+
+//ACRVulnerabilityConfig holds ACR api vulnerability information
+type ACRVulnerabilityConfig struct {
+	Description     string             `json:"description"`
+	DisplayName     string             `json:"displayName"`
+	ResourceDetails ACRResourceDetails `json:"resourceDetails"`
+	Status          ACRStatus          `json:"status"`
+	AdditionalData  ACRAdditionalData  `json:"additionalData"`
+	TimeGenerated   time.Time          `json:"timeGenerated"`
+	Remediation     string             `json:"remediation"`
+	ID              string             `json:"id"`
+	Category        string             `json:"category"`
+	Impact          string             `json:"impact"`
+}
+
+// ACRResourceDetails holds ACR vulnerability resource details
+type ACRResourceDetails struct {
+	ID     string `json:"id"`
+	Source string `json:"source"`
+}
+
+// ACRStatus holds  ACR vulnerability saverity details
+type ACRStatus struct {
+	Severity string `json:"severity"`
+	Code     string `json:"code"`
+}
+
+// ACRAdditionalData holds ACR vulnerability's additional data
+type ACRAdditionalData struct {
+	AssessedResourceType string          `json:"assessedResourceType"`
+	Type                 string          `json:"type"`
+	VendorReferences     []ACRVendorInfo `json:"vendorReferences"`
+	PublishedTime        time.Time       `json:"publishedTime"`
+	Patchable            bool            `json:"patchable"`
+	Cvss                 ACRCvss         `json:"cvss"`
+	RepositoryName       string          `json:"repositoryName"`
+	Cve                  []ACRCve        `json:"cve"`
+	RegistryHost         string          `json:"registryHost"`
+	ImageDigest          string          `json:"imageDigest"`
+	CicdData             ACRCicdData     `json:"cicdData"`
+}
+
+// ACRVendorInfo holds vendor information
+type ACRVendorInfo struct {
+	Title string `json:"title"`
+	Link  string `json:"link"`
+}
+
+// ACRCvss holds cvss score details in v2 and v3 vector
+type ACRCvss struct {
+	V2 ACRCvssBase `json:"2.0"`
+	V3 ACRCvssBase `json:"3.0"`
+}
+
+//ACRCvssBase base holds the actual cvss score of vulnerability eg.  "base": 7.8
+type ACRCvssBase struct {
+	Base float64 `json:"base"`
+}
+
+// ACRCve holds cve details such as cve id and link to cve details
+type ACRCve struct {
+	Title string `json:"title"`
+	Link  string `json:"link"`
+}
+
+//ACRCicdData holds information about the cicd job completion
+type ACRCicdData struct {
+	Status string `json:"status"`
+}
+
+// PrepareFromECRImageScanAttribute prepares cvss object from ECR image scan attribute
+func (cvss *CVSS) PrepareFromECRImageScanAttribute(attribute *ecr.Attribute) {
+	if strings.Contains(*attribute.Key, ecrCvss) {
+		switch *attribute.Key {
+		case ecrCvss + "2_" + ecrCvssVector:
+			cvss.V2Vector = *attribute.Value
+		case ecrCvss + "3_" + ecrCvssVector:
+			cvss.V3Vector = *attribute.Value
+		case ecrCvss + "2_" + ecrCvssScore:
+			if v, err := strconv.ParseFloat(*attribute.Value, 64); err == nil {
+				cvss.V2Score = v
+			}
+		case ecrCvss + "3_" + ecrCvssScore:
+			if v, err := strconv.ParseFloat(*attribute.Value, 64); err == nil {
+				cvss.V3Score = v
+			}
+		}
+	}
+}
+
+// PrepareFromECRImageScan prepares vulnerability object from ECR image scan findings
+func (v *Vulnerability) PrepareFromECRImageScan(imageScanFinding *ecr.ImageScanFinding) {
+	if imageScanFinding.Severity != nil {
+		v.Severity = strings.ToUpper(*imageScanFinding.Severity)
+	}
+	if imageScanFinding.Description != nil {
+		v.Description = *imageScanFinding.Description
+	}
+	if imageScanFinding.Name != nil {
+		v.VulnerabilityID = *imageScanFinding.Name
+	}
+	if imageScanFinding.Uri != nil {
+		v.PrimaryURL = *imageScanFinding.Uri
+	}
+	if v.PrimaryURL == "" {
+		v.PrimaryURL = primaryURL + v.VulnerabilityID
+	}
+	cvss := CVSS{}
+	for _, attr := range imageScanFinding.Attributes {
+		if attr.Key == nil || attr.Value == nil {
+			continue
+		} else if strings.EqualFold(*attr.Key, ecrPackageName) {
+			v.PkgName = *attr.Value
+		} else if strings.EqualFold(*attr.Key, ecrPackageVersion) {
+			v.InstalledVersion = *attr.Value
+		} else {
+			cvss.PrepareFromECRImageScanAttribute(attr)
+			vendorCVSS := make(VendorCVSS)
+			vendorCVSS[nvd] = cvss
+			v.CVSS = vendorCVSS
+		}
+	}
+}
+
+//PrepareFromACRImageScan - prepares vulnerability object from ACR image scan findings
+func (v *Vulnerability) PrepareFromACRImageScan(acrResponse ACRResponse) {
+	if acrResponse.Properties.ID == "" {
+		return
+	}
+	v.Description = acrResponse.Properties.Description
+	if acrResponse.Properties.AdditionalData.Cve != nil && len(acrResponse.Properties.AdditionalData.Cve) >= 1 {
+		v.VulnerabilityID = acrResponse.Properties.AdditionalData.Cve[0].Title
+		v.PrimaryURL = acrResponse.Properties.AdditionalData.Cve[0].Link
+	}
+	if v.PrimaryURL == "" {
+		v.PrimaryURL = primaryURL + v.VulnerabilityID
+	}
+
+	v.Severity = strings.ToUpper(acrResponse.Properties.Status.Severity)
+	vendorCVSS := make(VendorCVSS)
+	cvss := CVSS{
+		V2Score: acrResponse.Properties.AdditionalData.Cvss.V2.Base,
+		V3Score: acrResponse.Properties.AdditionalData.Cvss.V3.Base,
+	}
+	vendorCVSS[nvd] = cvss
+	v.CVSS = vendorCVSS
+}
+
+//PrepareFromGCRImageScan - prepares vulnerability object from GCP image scan findings
+func (v *Vulnerability) PrepareFromGCRImageScan(gcpVulnerability *grafeaspb.Occurrence) {
+	vul := gcpVulnerability.GetVulnerability()
+	v.Type = vul.GetType()
+	pkgIssue := vul.GetPackageIssue()
+	for _, pkg := range pkgIssue {
+		v.PkgName = pkg.GetAffectedPackage()
+		v.InstalledVersion = pkg.GetAffectedVersion().GetFullName()
+		v.FixedVersion = pkg.GetFixedVersion().GetFullName()
+	}
+
+	v.Severity = strings.ToUpper(vul.GetSeverity().String())
+	v.Description = vul.GetLongDescription()
+	noteURL := gcpVulnerability.GetNoteName()
+	noteURLSlice := strings.Split(noteURL, "/")
+	if len(noteURLSlice) > 0 {
+		v.VulnerabilityID = noteURLSlice[len(noteURLSlice)-1]
+	}
+	for _, url := range vul.GetRelatedUrls() {
+		v.References = append(v.References, url.GetUrl())
+	}
+	if v.PrimaryURL == "" {
+		v.PrimaryURL = primaryURL + v.VulnerabilityID
+	}
+	cvss := CVSS{
+		V2Score: float64(vul.GetCvssScore()),
+	}
+	vendorCVSS := make(VendorCVSS)
+	vendorCVSS[nvd] = cvss
+	v.CVSS = vendorCVSS
+}
diff --git a/pkg/iac-providers/terraform/commons/extract-container-images.go b/pkg/iac-providers/terraform/commons/extract-container-images.go
index 2ecb63af7..fca9322e3 100644
--- a/pkg/iac-providers/terraform/commons/extract-container-images.go
+++ b/pkg/iac-providers/terraform/commons/extract-container-images.go
@@ -73,8 +73,8 @@ func isAwsConatinerResource(resource *hclConfigs.Resource) bool {
 }
 
 //fetchConatinersFromAzureResource extracts all the containers from azure resource
-func fetchContainersFromAzureResource(resource jsonObj) []output.ContainerNameAndImage {
-	results := []output.ContainerNameAndImage{}
+func fetchContainersFromAzureResource(resource jsonObj) []output.ContainerDetails {
+	results := []output.ContainerDetails{}
 	if v, ok := resource[container]; ok {
 		if containers, vok := v.([]jsonObj); vok {
 			results = getContainers(containers)
@@ -84,8 +84,8 @@ func fetchContainersFromAzureResource(resource jsonObj) []output.ContainerNameAn
 }
 
 //fetchConatinersFromAwsResource extracts all the containers from aws ecs resource
-func fetchContainersFromAwsResource(resource jsonObj, hclBody *hclsyntax.Body, resourcePath string) []output.ContainerNameAndImage {
-	results := []output.ContainerNameAndImage{}
+func fetchContainersFromAwsResource(resource jsonObj, hclBody *hclsyntax.Body, resourcePath string) []output.ContainerDetails {
+	results := []output.ContainerDetails{}
 	if v, ok := resource[containerDefinitions]; ok {
 		def := v.(string)
 		if strings.HasPrefix(def, jsonCodeSuffix) {
@@ -117,7 +117,7 @@ func fetchContainersFromAwsResource(resource jsonObj, hclBody *hclsyntax.Body, r
 }
 
 //getContainersFromhclBody parses the attribute and creates container object
-func getContainersFromhclBody(hclBody *hclsyntax.Body) (results []output.ContainerNameAndImage) {
+func getContainersFromhclBody(hclBody *hclsyntax.Body) (results []output.ContainerDetails) {
 	for _, v := range hclBody.Attributes {
 		if v.Name == containerDefinitions {
 			switch v.Expr.(type) {
@@ -141,7 +141,7 @@ func getContainersFromhclBody(hclBody *hclsyntax.Body) (results []output.Contain
 							return
 						}
 						containerMap := containerTemp.(map[string]interface{})
-						tempContainer := output.ContainerNameAndImage{}
+						tempContainer := output.ContainerDetails{}
 						if image, iok := containerMap[image]; iok {
 							if imageName, ok := image.(string); ok {
 								tempContainer.Image = imageName
@@ -166,9 +166,9 @@ func getContainersFromhclBody(hclBody *hclsyntax.Body) (results []output.Contain
 }
 
 // getContainers reads and creates container config
-func getContainers(containers []jsonObj) (results []output.ContainerNameAndImage) {
+func getContainers(containers []jsonObj) (results []output.ContainerDetails) {
 	for _, container := range containers {
-		tempContainer := output.ContainerNameAndImage{}
+		tempContainer := output.ContainerDetails{}
 		if image, iok := container[image]; iok {
 			if imageName, ok := image.(string); ok {
 				tempContainer.Image = imageName
@@ -188,7 +188,7 @@ func getContainers(containers []jsonObj) (results []output.ContainerNameAndImage
 }
 
 //extractContainerImagesFromk8sResources extracts containers from k8s resource
-func extractContainerImagesFromk8sResources(resource *hclConfigs.Resource, body *hclsyntax.Body) (containers, initContainers []output.ContainerNameAndImage) {
+func extractContainerImagesFromk8sResources(resource *hclConfigs.Resource, body *hclsyntax.Body) (containers, initContainers []output.ContainerDetails) {
 	for _, block := range body.Blocks {
 		if block.Type == spec {
 			containerBlocks, initContainerBlocks := getContainerAndInitContainerFromSpecBlocks(block.Body)
@@ -235,9 +235,9 @@ func getContainerAndInitContainerFromTemplateBlocks(templateBlocks []*hclsyntax.
 }
 
 //getContainerConfigFromContainerBlock creates container config from container block of resource
-func getContainerConfigFromContainerBlock(containerBlocks []*hclsyntax.Block) (containerImages []output.ContainerNameAndImage) {
+func getContainerConfigFromContainerBlock(containerBlocks []*hclsyntax.Block) (containerImages []output.ContainerDetails) {
 	for _, conatainerBlock := range containerBlocks {
-		containerImage := output.ContainerNameAndImage{}
+		containerImage := output.ContainerDetails{}
 		for _, attr := range conatainerBlock.Body.Attributes {
 			if attr.Name == image {
 				containerImage.Image = getValueFromCtyExpr(attr.Expr)
diff --git a/pkg/iac-providers/terraform/commons/resource.go b/pkg/iac-providers/terraform/commons/resource.go
index 7aaea3307..b691db38b 100644
--- a/pkg/iac-providers/terraform/commons/resource.go
+++ b/pkg/iac-providers/terraform/commons/resource.go
@@ -76,7 +76,7 @@ func CreateResourceConfig(managedResource *hclConfigs.Resource) (resourceConfig
 }
 
 //findContainers finds containers defined in resource
-func findContainers(managedResource *hclConfigs.Resource, jsonBody jsonObj, hclBody *hclsyntax.Body) (containers []output.ContainerNameAndImage, initContainers []output.ContainerNameAndImage) {
+func findContainers(managedResource *hclConfigs.Resource, jsonBody jsonObj, hclBody *hclsyntax.Body) (containers []output.ContainerDetails, initContainers []output.ContainerDetails) {
 	if isKuberneteResource(managedResource) {
 		containers, initContainers = extractContainerImagesFromk8sResources(managedResource, hclBody)
 	} else if isAzureConatinerResource(managedResource) {
diff --git a/pkg/k8s/admission-webhook/validating-webhook.go b/pkg/k8s/admission-webhook/validating-webhook.go
index eb69b03d7..51f063e56 100644
--- a/pkg/k8s/admission-webhook/validating-webhook.go
+++ b/pkg/k8s/admission-webhook/validating-webhook.go
@@ -191,10 +191,10 @@ func (w ValidatingWebhook) scanK8sFile(filePath string) (runtime.Output, error)
 
 	if flag.Lookup("test.v") != nil {
 		executor, err = runtime.NewExecutor("k8s", "v1", []string{"k8s"},
-			filePath, "", []string{testPoliciesPath}, []string{}, []string{}, []string{}, "", false, false)
+			filePath, "", []string{testPoliciesPath}, []string{}, []string{}, []string{}, "", false, false, false)
 	} else {
 		executor, err = runtime.NewExecutor("k8s", "v1", []string{"k8s"},
-			filePath, "", []string{}, []string{}, []string{}, []string{}, "", false, false)
+			filePath, "", []string{}, []string{}, []string{}, []string{}, "", false, false, false)
 	}
 	if err != nil {
 		zap.S().Errorf("failed to create runtime executer: '%v'", err)
diff --git a/pkg/policy/types.go b/pkg/policy/types.go
index 98ab9ea1f..6d0c9918f 100644
--- a/pkg/policy/types.go
+++ b/pkg/policy/types.go
@@ -41,6 +41,7 @@ func (me EngineOutput) AsViolationStore() results.ViolationStore {
 	}
 	return results.ViolationStore{
 		Violations:        me.Violations,
+		Vulnerabilities:   me.Vulnerabilities,
 		SkippedViolations: me.SkippedViolations,
 		PassedRules:       me.PassedRules,
 		Summary:           me.Summary,
diff --git a/pkg/results/types.go b/pkg/results/types.go
index e90159651..bfb2bc3ed 100644
--- a/pkg/results/types.go
+++ b/pkg/results/types.go
@@ -51,11 +51,12 @@ type PassedRule struct {
 
 // ViolationStore Storage area for violation data
 type ViolationStore struct {
-	DirScanErrors     []DirScanErr  `json:"scan_errors,omitempty" yaml:"scan_errors,omitempty" xml:"scan_errors>scan_error,omitempty"`
-	PassedRules       []*PassedRule `json:"passed_rules,omitempty" yaml:"passed_rules,omitempty" xml:"passed_rules>passed_rule,omitempty"`
-	Violations        []*Violation  `json:"violations" yaml:"violations" xml:"violations>violation"`
-	SkippedViolations []*Violation  `json:"skipped_violations" yaml:"skipped_violations" xml:"skipped_violations>violation"`
-	Summary           ScanSummary   `json:"scan_summary" yaml:"scan_summary" xml:"scan_summary"`
+	DirScanErrors     []DirScanErr     `json:"scan_errors,omitempty" yaml:"scan_errors,omitempty" xml:"scan_errors>scan_error,omitempty"`
+	PassedRules       []*PassedRule    `json:"passed_rules,omitempty" yaml:"passed_rules,omitempty" xml:"passed_rules>passed_rule,omitempty"`
+	Violations        []*Violation     `json:"violations" yaml:"violations" xml:"violations>violation"`
+	SkippedViolations []*Violation     `json:"skipped_violations" yaml:"skipped_violations" xml:"skipped_violations>violation"`
+	Vulnerabilities   []*Vulnerability `json:"vulnerabilities,omitempty" yaml:"vulnerabilities,omitempty"`
+	Summary           ScanSummary      `json:"scan_summary" yaml:"scan_summary" xml:"scan_summary"`
 }
 
 // ScanSummary will hold the default scan summary data
@@ -66,6 +67,7 @@ type ScanSummary struct {
 	ShowViolationDetails bool   `json:"-" yaml:"-" xml:"-"`
 	TotalPolicies        int    `json:"policies_validated" yaml:"policies_validated" xml:"policies_validated,attr"`
 	ViolatedPolicies     int    `json:"violated_policies" yaml:"violated_policies" xml:"violated_policies,attr"`
+	Vulnerabilities      *int   `json:"vulnerabilities,omitempty" yaml:"vulnerabilities,omitempty"`
 	LowCount             int    `json:"low" yaml:"low" xml:"low,attr"`
 	MediumCount          int    `json:"medium" yaml:"medium" xml:"medium,attr"`
 	HighCount            int    `json:"high" yaml:"high" xml:"high,attr"`
@@ -73,6 +75,31 @@ type ScanSummary struct {
 	TotalTime int64 `json:"-" yaml:"-" xml:"-"`
 }
 
+// CVSS will hold cvss score details
+type CVSS struct {
+	V2Vector string  `json:"v2_vector,omitempty" yaml:"v2_vector,omitempty" xml:"v2_vector,attr,omitempty"`
+	V3Vector string  `json:"v3_vector,omitempty" yaml:"v3_vector,omitempty" xml:"v3_vector,attr,omitempty"`
+	V2Score  float64 `json:"v2_score,omitempty" yaml:"v2_score,omitempty" xml:"v2_score,attr,omitempty"`
+	V3Score  float64 `json:"v3_score,omitempty" yaml:"v3_score,omitempty" xml:"v3_score,attr,omitempty"`
+}
+
+//Vulnerability will hold vulnerability details that will be displayed in scan summary
+type Vulnerability struct {
+	Image            string `json:"image" yaml:"image"`
+	Container        string `json:"container,omitempty" yaml:"container,omitempty" xml:"container,attr"`
+	Package          string `json:"package,omitempty" yaml:"package,omitempty" xml:"package,attr"`
+	Severity         string `json:"severity" yaml:"severity" xml:"severity,attr"`
+	CVSSScore        CVSS   `json:"cvss_score,omitempty" yaml:"cvss_score,omitempty" xml:"cvss_score>cvss_score,omitempty"`
+	InstalledVersion string `json:"installed_version,omitempty" yaml:"installed_version,omitempty" xml:"installed_version,attr,omitempty"`
+	Description      string `json:"description,omitempty" yaml:"description,omitempty" xml:"description,attr,omitempty"`
+	VulnerabilityID  string `json:"vulnerability_id" yaml:"vulnerability_id" xml:"vulnerability_id,attr"`
+	File             string `json:"file,omitempty" yaml:"file,omitempty" xml:"file,attr,omitempty"`
+	LineNumber       int    `json:"line,omitempty" yaml:"line,omitempty" xml:"line,attr,omitempty"`
+	PrimaryURL       string `json:"primary_url,omitempty" yaml:"primary_url,omitempty" xml:"primary_url,attr,omitempty"`
+	ResourceName     string `json:"resource_name" yaml:"resource_name" xml:"resource_name,attr"`
+	ResourceType     string `json:"resource_type" yaml:"resource_type" xml:"resource_type,attr"`
+}
+
 // DirScanErr holds details for an error that occurred while iac providers scans a directory
 type DirScanErr struct {
 	IacType    string `json:"iac_type" yaml:"iac_type" xml:"iac_type,attr"`
diff --git a/pkg/runtime/executor.go b/pkg/runtime/executor.go
index e33a95381..f4eee9395 100644
--- a/pkg/runtime/executor.go
+++ b/pkg/runtime/executor.go
@@ -20,6 +20,7 @@ import (
 	"sort"
 
 	"github.com/accurics/terrascan/pkg/policy/opa"
+	"github.com/accurics/terrascan/pkg/vulnerability"
 
 	"go.uber.org/zap"
 
@@ -38,35 +39,44 @@ const (
 
 // Executor object
 type Executor struct {
-	filePath          string
-	dirPath           string
-	policyPath        []string
-	iacType           string
-	iacVersion        string
-	scanRules         []string
-	skipRules         []string
-	iacProviders      []iacProvider.IacProvider
-	policyEngines     []policy.Engine
-	notifiers         []notifications.Notifier
-	categories        []string
-	policyTypes       []string
-	severity          string
-	nonRecursive      bool
-	useTerraformCache bool
+	filePath            string
+	dirPath             string
+	policyPath          []string
+	iacType             string
+	iacVersion          string
+	scanRules           []string
+	skipRules           []string
+	iacProviders        []iacProvider.IacProvider
+	policyEngines       []policy.Engine
+	notifiers           []notifications.Notifier
+	categories          []string
+	policyTypes         []string
+	severity            string
+	nonRecursive        bool
+	useTerraformCache   bool
+	findVulnerabilities bool
+	vulnerabilityEngine vulnerability.Engine
 }
 
 // NewExecutor creates a runtime object
-func NewExecutor(iacType, iacVersion string, policyTypes []string, filePath, dirPath string, policyPath, scanRules, skipRules, categories []string, severity string, nonRecursive, useTerraformCache bool) (e *Executor, err error) {
+func NewExecutor(iacType, iacVersion string, policyTypes []string, filePath, dirPath string, policyPath, scanRules, skipRules, categories []string, severity string, nonRecursive, useTerraformCache, findVulnerabilities bool) (e *Executor, err error) {
 	e = &Executor{
-		filePath:          filePath,
-		dirPath:           dirPath,
-		policyPath:        policyPath,
-		policyTypes:       policyTypes,
-		iacType:           iacType,
-		iacVersion:        iacVersion,
-		iacProviders:      make([]iacProvider.IacProvider, 0),
-		nonRecursive:      nonRecursive,
-		useTerraformCache: useTerraformCache,
+		filePath:            filePath,
+		dirPath:             dirPath,
+		policyPath:          policyPath,
+		policyTypes:         policyTypes,
+		iacType:             iacType,
+		iacVersion:          iacVersion,
+		iacProviders:        make([]iacProvider.IacProvider, 0),
+		nonRecursive:        nonRecursive,
+		useTerraformCache:   useTerraformCache,
+		findVulnerabilities: findVulnerabilities,
+	}
+
+	// assigning vulnerabilityEngine
+	vulnerabilityEngine, err := vulnerability.NewVulEngine()
+	if err == nil {
+		e.vulnerabilityEngine = vulnerabilityEngine
 	}
 
 	// read config file and update scan and skip rules
@@ -180,14 +190,13 @@ func (e *Executor) Execute(configOnly bool) (results Output, err error) {
 
 	var merr *multierror.Error
 	var resourceConfig output.AllResourceConfigs
-
+	options := e.buildOptions()
 	// when dir path has value, only then it will 'all iac' scan
 	// when file path has value, we will go with the only iac provider in the list
 	if e.dirPath != "" {
 		// get all resource configs in the directory
 		resourceConfig, merr = e.getResourceConfigs()
 	} else {
-		options := e.buildOptions()
 		// create results output from Iac provider
 		// iac providers will contain one element
 		resourceConfig, err = e.iacProviders[0].LoadIacFile(e.filePath, options)
@@ -207,6 +216,10 @@ func (e *Executor) Execute(configOnly bool) (results Output, err error) {
 	// update results with resource config
 	results.ResourceConfig = resourceConfig
 
+	if e.findVulnerabilities {
+		results.ResourceConfig = e.fetchVulnerabilities(&results, options)
+	}
+
 	if configOnly {
 		return results, nil
 	}
@@ -219,6 +232,9 @@ func (e *Executor) Execute(configOnly bool) (results Output, err error) {
 		return results, err
 	}
 
+	if e.findVulnerabilities {
+		e.reportVulnerabilities(&results, options)
+	}
 	resourcePath := e.filePath
 	if resourcePath == "" {
 		resourcePath = e.dirPath
@@ -307,6 +323,25 @@ func (e *Executor) findViolations(results *Output) error {
 	return nil
 }
 
+// fetchVulnerabilities adds vulnerability findings in resource config object
+func (e *Executor) fetchVulnerabilities(results *Output, options map[string]interface{}) output.AllResourceConfigs {
+
+	return e.vulnerabilityEngine.FetchVulnerabilities(results.ResourceConfig, options)
+
+}
+
+// reportVulnerabilities adds the found vulnerability data to scan summary output
+func (e *Executor) reportVulnerabilities(results *Output, options map[string]interface{}) {
+	violations := results.Violations.AsViolationStore()
+	vulnerabilityData := e.vulnerabilityEngine.ReportVulnerability(vulnerability.EngineInput{InputData: &results.ResourceConfig}, options)
+	if vulnerabilityData.ViolationStore != nil {
+		violations.Vulnerabilities = vulnerabilityData.Vulnerabilities
+		vulnCount := len(vulnerabilityData.Vulnerabilities)
+		violations.Summary.Vulnerabilities = &vulnCount
+	}
+	results.Violations = policy.EngineOutputFromViolationStore(&violations)
+}
+
 // implementsSubFolderScan checks if given iac type supports sub folder scanning
 func implementsSubFolderScan(iacType string, nonRecursive bool) bool {
 	// iac providers that support sub folder scanning
diff --git a/pkg/vulnerability/acr.go b/pkg/vulnerability/acr.go
new file mode 100644
index 000000000..4db63708f
--- /dev/null
+++ b/pkg/vulnerability/acr.go
@@ -0,0 +1,225 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/Azure/azure-sdk-for-go/profiles/preview/preview/containerregistry/runtime/containerregistry"
+	"github.com/Azure/azure-sdk-for-go/services/resourcegraph/mgmt/2021-03-01/resourcegraph"
+	"github.com/Azure/go-autorest/autorest"
+	"github.com/Azure/go-autorest/autorest/azure"
+	"github.com/Azure/go-autorest/autorest/azure/auth"
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+	"go.uber.org/zap"
+)
+
+const (
+	azureURL              = ".azurecr.io"
+	azureRegistryPassword = "AZURE_ACR_PASSWORD"
+)
+
+//ACR  acr container registry
+type ACR struct {
+	scanner acrScanner
+}
+
+//scanner implementor for acrScanner interface
+type scanner struct{}
+
+func init() {
+	RegisterContainerRegistry("acr", &ACR{
+		scanner: scanner{},
+	})
+}
+
+//acrScanner holds external Azure methods
+type acrScanner interface {
+	newAuthorizerFromFile() (autorest.Authorizer, error)
+	newResourcegraphClient() resourcegraph.BaseClient
+	getResources(context.Context, resourcegraph.QueryRequest, resourcegraph.BaseClient) (resourcegraph.QueryResponse, error)
+	newBasicAuthorizer(string, string) *autorest.BasicAuthorizer
+	newTagClient(string) containerregistry.TagClient
+	getAttributes(context.Context, string, string, containerregistry.TagClient) (containerregistry.TagAttributes, error)
+}
+
+//CheckRegistry verify provided image belongs to acr registry
+func (a *ACR) checkRegistry(image string) bool {
+	domain := GetDomain(image)
+	return strings.HasSuffix(domain, azureURL)
+}
+
+//newTagClient returns containerregistry tag client
+func (scanner) newTagClient(loginURL string) containerregistry.TagClient {
+	return containerregistry.NewTagClient(loginURL)
+}
+
+//newBasicAuthorizer returns basic athorizer
+func (scanner) newBasicAuthorizer(username string, password string) *autorest.BasicAuthorizer {
+	return autorest.NewBasicAuthorizer(username, password)
+}
+
+//newAuthorizerFromFile creates and returns autherizer
+func (scanner) newAuthorizerFromFile() (autorest.Authorizer, error) {
+	authorizer, err := auth.NewAuthorizerFromFile(azure.PublicCloud.ResourceManagerEndpoint)
+	if err != nil {
+		zap.S().Errorf("failed to authorize : %v ", err)
+		return nil, err
+	}
+	return authorizer, nil
+}
+
+//newResourcegraphClient returns new resourcegraph client
+func (scanner) newResourcegraphClient() resourcegraph.BaseClient {
+	return resourcegraph.New()
+}
+
+//getResources returns all the vulnerability resources
+func (scanner) getResources(ctx context.Context, request resourcegraph.QueryRequest, client resourcegraph.BaseClient) (resourcegraph.QueryResponse, error) {
+	return client.Resources(ctx, request)
+}
+
+//GetAttributes returns tag attributes
+func (scanner) getAttributes(ctx context.Context, name string, reference string, client containerregistry.TagClient) (result containerregistry.TagAttributes, err error) {
+	return client.GetAttributes(ctx, name, reference)
+}
+
+// GetVulnerabilities - get vulnerabilities from acr registry
+func (a *ACR) getVulnerabilities(container output.ContainerDetails, options map[string]interface{}) (vulnerabilities []output.Vulnerability) {
+	results, err := a.ScanImage(container.Image)
+	if err != nil {
+		zap.S().Errorf("error finding vulnerabilities for image %s : %v", container.Image, err)
+		return
+	}
+	for _, result := range results {
+		vulnerability := output.Vulnerability{}
+		vulnerability.PrepareFromACRImageScan(result)
+		if vulnerability.VulnerabilityID != "" {
+			vulnerabilities = append(vulnerabilities, vulnerability)
+		}
+	}
+	return
+}
+
+//ScanImage - get the image scan result from ACR registry
+func (a *ACR) ScanImage(image string) ([]output.ACRResponse, error) {
+	results := []output.ACRResponse{}
+	resourcegraphClient := a.scanner.newResourcegraphClient()
+
+	authrizer, err := a.scanner.newAuthorizerFromFile()
+	if err != nil {
+		zap.S().Errorf("failed to authorize for image %s ", image)
+		return results, err
+	}
+	resourcegraphClient.Authorizer = authrizer
+
+	imageDetails, isValidImage := a.getACRImageDetails(image, authrizer)
+	if !isValidImage {
+		zap.S().Errorf(invalidImageReferenceMsg, image)
+		return results, fmt.Errorf(invalidImageReferenceMsg, image)
+	}
+
+	RequestOptions := resourcegraph.QueryRequestOptions{
+		ResultFormat: resourcegraph.ResultFormatObjectArray,
+	}
+
+	query := `securityresources | where type == "microsoft.security/assessments"
+	| summarize by assessmentKey=name 
+	| join kind=inner (
+		securityresources
+		 | where type == "microsoft.security/assessments/subassessments"
+		 | extend assessmentKey = extract(".*assessments/(.+?)/.*",1,  id)
+	 ) on assessmentKey
+	| project parse_json(properties)
+	| where properties.additionalData.repositoryName =="` + imageDetails.Repository +
+		`" and properties.additionalData.registryHost == "` + imageDetails.Registry +
+		`" and properties.additionalData.imageDigest == "` + imageDetails.Digest + `"`
+
+	request := resourcegraph.QueryRequest{
+		Query:   &query,
+		Options: &RequestOptions,
+	}
+
+	// Run the query and get the results
+	var response, queryErr = a.scanner.getResources(context.Background(), request, resourcegraphClient)
+	if queryErr != nil {
+		zap.S().Errorf(errorScanningMsg, image, queryErr)
+		return results, queryErr
+	}
+
+	jsonData, err := json.Marshal(response.Data)
+	if err != nil {
+		zap.S().Errorf("error marshaling image %s scan results", image)
+		return results, fmt.Errorf("error marshaling image %s scan results", image)
+	}
+	err = json.Unmarshal([]byte(jsonData), &results)
+	if err != nil {
+		zap.S().Errorf("error unmarshaling image %s scan results", image)
+		return results, fmt.Errorf("error unmarshaling image %s scan results", image)
+	}
+	return results, nil
+}
+
+// getImageNameHostDigest - gets image tag, host and digest from iamge name
+func (a *ACR) getACRImageDetails(image string, authrizer autorest.Authorizer) (imageDetails ImageDetails, validImage bool) {
+	validImage = true
+	imageDetails = GetImageDetails(image, imageDetails)
+	if imageDetails.Tag == "" && imageDetails.Repository == "" {
+		validImage = false
+		return
+	}
+	if imageDetails.Tag == "" {
+		imageDetails.Tag = defaultTagValue
+	}
+	if imageDetails.Digest == "" {
+		loginURL := fmt.Sprintf("https://%s", imageDetails.Registry)
+		digest := a.getImageDigestFromTag(image, imageDetails, loginURL)
+		if digest == "" {
+			validImage = false
+			return
+		}
+		imageDetails.Digest = digest
+	}
+	return
+
+}
+
+// getImageDigestFromTag - get image digest from repository for given tag
+func (a *ACR) getImageDigestFromTag(image string, imageDetails ImageDetails, loginURL string) (digest string) {
+	zap.S().Debug("fetching digest for image %s", image)
+	password := os.Getenv(azureRegistryPassword)
+	parts := strings.Split(imageDetails.Registry, azureURL)
+	if len(parts) < 2 {
+		return
+	}
+	basicAuthorizer := a.scanner.newBasicAuthorizer(parts[0], password)
+	client := a.scanner.newTagClient(loginURL)
+	client.Authorizer = basicAuthorizer
+	result, err := a.scanner.getAttributes(context.Background(), imageDetails.Repository, imageDetails.Tag, client)
+	if err != nil {
+		zap.S().Errorf("error getting image  %s digest %v", image, err)
+		return
+	}
+	if result.Attributes != nil && result.Attributes.Digest != nil {
+		digest = *result.Attributes.Digest
+	}
+	return
+}
diff --git a/pkg/vulnerability/ecr.go b/pkg/vulnerability/ecr.go
new file mode 100644
index 000000000..a2fd24dbc
--- /dev/null
+++ b/pkg/vulnerability/ecr.go
@@ -0,0 +1,211 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"context"
+	"fmt"
+	"strings"
+	"time"
+
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/aws/session"
+	"github.com/aws/aws-sdk-go/service/ecr"
+	"go.uber.org/zap"
+)
+
+const (
+	ecrURL = "amazonaws.com"
+)
+
+var (
+	invalidImageReferenceMsg = "invalid image reference %s "
+	errorScanningMsg         = "error scanning image %s : %v"
+)
+
+//ECR  ecr container registry
+type ECR struct {
+	scanner ecrScanner
+}
+
+//scanner implementor for ecrScanner interface
+type escanner struct{}
+
+func init() {
+	RegisterContainerRegistry("ecr", &ECR{
+		scanner: escanner{},
+	})
+}
+
+//ecrScanner  holds external ECR methods
+type ecrScanner interface {
+	newClient() *ecr.ECR
+	describeImageScanFindingsWithContext(ctx context.Context, client *ecr.ECR, input *ecr.DescribeImageScanFindingsInput, opts ...request.Option) (*ecr.DescribeImageScanFindingsOutput, error)
+	startImageScanWithContext(ctx context.Context, client *ecr.ECR, input *ecr.StartImageScanInput, opts ...request.Option) (*ecr.StartImageScanOutput, error)
+	waitUntilImageScanComplete(client *ecr.ECR, input *ecr.DescribeImageScanFindingsInput) error
+}
+
+// newClient returns new ECR client
+func (escanner) newClient() *ecr.ECR {
+	session := session.Must(session.NewSession())
+	// Create a ECR client from just a session.
+	return ecr.New(session)
+}
+
+// describeImageScanFindingsWithContext returns image scan findings
+func (escanner) describeImageScanFindingsWithContext(ctx context.Context, client *ecr.ECR, input *ecr.DescribeImageScanFindingsInput, opts ...request.Option) (*ecr.DescribeImageScanFindingsOutput, error) {
+	return client.DescribeImageScanFindingsWithContext(ctx, input)
+}
+
+// waitUntilImageScanComplete use to wait until image scan is complete
+func (escanner) waitUntilImageScanComplete(client *ecr.ECR, input *ecr.DescribeImageScanFindingsInput) error {
+	return client.WaitUntilImageScanComplete(input)
+}
+
+//startImageScanWithContext start image vulnerability scan
+func (escanner) startImageScanWithContext(ctx context.Context, client *ecr.ECR, input *ecr.StartImageScanInput, opts ...request.Option) (*ecr.StartImageScanOutput, error) {
+	return client.StartImageScanWithContext(ctx, input)
+}
+
+//CheckRegistry verify provided image belongs to ecr registry
+func (e *ECR) checkRegistry(image string) bool {
+	domain := GetDomain(image)
+	return strings.HasSuffix(domain, ecrURL)
+}
+
+// GetVulnerabilities - get vulnerabilities from ecr registry
+func (e *ECR) getVulnerabilities(container output.ContainerDetails, options map[string]interface{}) (vulnerabilities []output.Vulnerability) {
+	results, err := e.ScanImage(context.Background(), container.Image)
+	if err != nil {
+		zap.S().Errorf("error finding vulnerabilities for image %s : %v", container.Image, err)
+		return
+	}
+	hasFindings := results != nil &&
+		results.ImageScanFindings != nil &&
+		results.ImageScanFindings.Findings != nil
+	if hasFindings {
+		for _, result := range results.ImageScanFindings.Findings {
+			vulnerability := output.Vulnerability{}
+			vulnerability.PrepareFromECRImageScan(result)
+			vulnerabilities = append(vulnerabilities, vulnerability)
+		}
+	}
+	return vulnerabilities
+}
+
+// ScanImage calles aws ecr api to get image scan details
+func (e *ECR) ScanImage(ctx context.Context, image string) (*ecr.DescribeImageScanFindingsOutput, error) {
+	client := e.scanner.newClient()
+
+	imageDetails := ImageDetails{}
+	imageDetails = GetImageDetails(image, imageDetails)
+
+	if imageDetails.Tag == "" && imageDetails.Repository == "" {
+		zap.S().Errorf(invalidImageReferenceMsg, image)
+		return nil, fmt.Errorf(invalidImageReferenceMsg, image)
+	}
+
+	if imageDetails.Tag == "" && imageDetails.Digest == "" {
+		imageDetails.Tag = defaultTagValue
+	}
+
+	return e.GetImageScanResult(ctx, client, image, imageDetails)
+
+}
+
+// StartImageScan starts the scan of provided image
+func (e *ECR) StartImageScan(ctx context.Context, client *ecr.ECR, image string, imageDetails ImageDetails) error {
+	imageIdentifier := ecr.ImageIdentifier{}
+	if imageDetails.Digest != "" {
+		imageIdentifier.ImageDigest = &imageDetails.Digest
+	} else {
+		imageIdentifier.ImageTag = &imageDetails.Tag
+	}
+	input := ecr.StartImageScanInput{
+		ImageId:        &imageIdentifier,
+		RepositoryName: &imageDetails.Repository,
+	}
+
+	if _, err := e.scanner.startImageScanWithContext(ctx, client, &input); err != nil {
+		zap.S().Errorf(errorScanningMsg, image, err)
+		return err
+	}
+
+	describeImageScanFindingsInput := ecr.DescribeImageScanFindingsInput{
+		ImageId:        &imageIdentifier,
+		RepositoryName: &imageDetails.Repository,
+	}
+
+	// wait until scan of image is complete
+	if err := e.scanner.waitUntilImageScanComplete(client, &describeImageScanFindingsInput); err != nil {
+		zap.S().Errorf(errorScanningMsg, image, err)
+		return err
+	}
+	return nil
+}
+
+// GetImageScanResult get the scan result from ECR
+func (e *ECR) GetImageScanResult(ctx context.Context, client *ecr.ECR, image string, imageDetails ImageDetails) (*ecr.DescribeImageScanFindingsOutput, error) {
+	imageIdentifier := ecr.ImageIdentifier{}
+	if imageDetails.Digest != "" {
+		imageIdentifier.ImageDigest = &imageDetails.Digest
+	} else {
+		imageIdentifier.ImageTag = &imageDetails.Tag
+	}
+	describeImageScanFindingsInput := ecr.DescribeImageScanFindingsInput{
+		ImageId:        &imageIdentifier,
+		RepositoryName: &imageDetails.Repository,
+	}
+	results, err := e.scanner.describeImageScanFindingsWithContext(ctx, client, &describeImageScanFindingsInput)
+	if err != nil {
+		if _, ok := err.(*ecr.ScanNotFoundException); ok {
+			err := e.StartImageScan(ctx, client, image, imageDetails)
+			if err != nil {
+				return results, err
+			}
+			return e.GetImageScanResult(ctx, client, image, imageDetails)
+		}
+		zap.S().Errorf(errorScanningMsg, image, err)
+		return results, err
+	}
+	hasFindings := results != nil &&
+		results.ImageScanStatus != nil &&
+		results.ImageScanStatus.Status != nil &&
+		results.ImageScanFindings != nil &&
+		results.ImageScanFindings.ImageScanCompletedAt != nil
+
+	if hasFindings {
+		if strings.EqualFold(*results.ImageScanStatus.Status, ecr.ScanStatusComplete) &&
+			(*results.ImageScanFindings.ImageScanCompletedAt).Before(time.Now().Add(24*time.Hour)) {
+			return results, nil
+		} else if strings.EqualFold(*results.ImageScanStatus.Status, ecr.ScanStatusFailed) {
+			return results, nil
+		} else if strings.EqualFold(*results.ImageScanStatus.Status, ecr.ScanStatusInProgress) {
+			return e.GetImageScanResult(ctx, client, image, imageDetails)
+		} else if strings.EqualFold(*results.ImageScanStatus.Status, ecr.ScanStatusComplete) &&
+			!((*results.ImageScanFindings.ImageScanCompletedAt).Before(time.Now().Add(24 * time.Hour))) {
+			err := e.StartImageScan(ctx, client, image, imageDetails)
+			if err != nil {
+				return results, err
+			}
+			return e.GetImageScanResult(ctx, client, image, imageDetails)
+		}
+
+	}
+	return results, nil
+}
diff --git a/pkg/vulnerability/gcr.go b/pkg/vulnerability/gcr.go
new file mode 100644
index 000000000..4b82348dd
--- /dev/null
+++ b/pkg/vulnerability/gcr.go
@@ -0,0 +1,260 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"context"
+	"fmt"
+	"os"
+	"strings"
+
+	containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
+	"github.com/GoogleCloudPlatform/docker-credential-gcr/config"
+	"github.com/GoogleCloudPlatform/docker-credential-gcr/credhelper"
+	"github.com/GoogleCloudPlatform/docker-credential-gcr/store"
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+	"github.com/google/go-containerregistry/pkg/authn"
+	"github.com/google/go-containerregistry/pkg/name"
+	"github.com/google/go-containerregistry/pkg/v1/remote"
+	"go.uber.org/zap"
+	"google.golang.org/api/iterator"
+	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
+)
+
+const (
+	kind           = "VULNERABILITY"
+	gcrURL         = "gcr.io"
+	gcrArtifactURL = "docker.pkg.dev"
+	googlCredPath  = "GOOGLE_APPLICATION_CREDENTIALS"
+)
+
+var (
+	failToGetDigestMsg = "failed to get image digest for image %s : %v"
+)
+
+// gcrScanner  holds external GCR methods
+type gcrScanner interface {
+	newClient(context.Context) (*containeranalysis.Client, error)
+	close(client *containeranalysis.Client) error
+	listOccurrences(ctx context.Context, client *containeranalysis.Client, req *grafeaspb.ListOccurrencesRequest) ([]*grafeaspb.Occurrence, error)
+}
+
+//scanner implementor for gcrScanner interface
+type gscanner struct{}
+
+//GCR  gcr container registry
+type GCR struct {
+	scanner gcrScanner
+}
+
+func init() {
+	RegisterContainerRegistry("gcr", &GCR{
+		scanner: gscanner{},
+	})
+}
+
+//newClient  returns new container analysis client
+func (gscanner) newClient(ctx context.Context) (*containeranalysis.Client, error) {
+	return containeranalysis.NewClient(ctx)
+}
+
+//close closes container analysis client
+func (gscanner) close(client *containeranalysis.Client) error {
+	return client.Close()
+}
+
+//listOccurrences returns all image vulnerability Occurrences
+func (gscanner) listOccurrences(ctx context.Context, client *containeranalysis.Client, req *grafeaspb.ListOccurrencesRequest) ([]*grafeaspb.Occurrence, error) {
+	output := client.GetGrafeasClient().ListOccurrences(ctx, req)
+	occurrences := []*grafeaspb.Occurrence{}
+	for {
+		occ, err := output.Next()
+		if err != nil {
+			if err == iterator.Done {
+				break
+			}
+			zap.S().Errorf(errorScanningMsg, "", err)
+			return occurrences, err
+		}
+
+		occurrences = append(occurrences, occ)
+	}
+	return occurrences, nil
+}
+
+//CheckRegistry verify provided image belongs to gcr registry
+func (g *GCR) checkRegistry(image string) bool {
+	host := GetDomain(image)
+	return strings.HasSuffix(host, gcrURL) || strings.HasSuffix(host, gcrArtifactURL)
+}
+
+// GetVulnerabilities - get vulnerabilities from gcr registry
+func (g *GCR) getVulnerabilities(container output.ContainerDetails, options map[string]interface{}) (vulnerabilities []output.Vulnerability) {
+	results, err := g.ScanImage(container.Image)
+	if err != nil {
+		zap.S().Errorf("error finding vulnerabilities for image %s : %v", container.Image, err)
+		return
+	}
+	for _, result := range results {
+		vulnerability := output.Vulnerability{}
+		vulnerability.PrepareFromGCRImageScan(result)
+		vulnerabilities = append(vulnerabilities, vulnerability)
+	}
+	return
+}
+
+// ScanImage get the image scan result from GCR registry
+func (g *GCR) ScanImage(image string) (result []*grafeaspb.Occurrence, err error) {
+	ctx := context.Background()
+
+	if image, err = getImageNameCompatibleForScan(image); err != nil {
+		return nil, err
+	}
+
+	projectID, err := getProjectIDFromImageName(image)
+	if err != nil {
+		return nil, err
+	}
+
+	resourceURL := fmt.Sprintf("https://%s", image)
+
+	client, err := g.scanner.newClient(ctx)
+	if err != nil {
+		zap.S().Errorf(errorScanningMsg, image, err)
+		return result, err
+	}
+
+	defer g.scanner.close(client)
+
+	req := &grafeaspb.ListOccurrencesRequest{
+		Parent: fmt.Sprintf("projects/%s", projectID),
+		Filter: fmt.Sprintf("resourceUrl = %q kind = %q", resourceURL, kind),
+	}
+
+	return g.scanner.listOccurrences(ctx, client, req)
+
+}
+
+// getImageNameCompatibleForScan - returns image name which has digest
+func getImageNameCompatibleForScan(image string) (string, error) {
+	imageDetails := ImageDetails{}
+
+	imageDetails = GetImageDetails(image, imageDetails)
+	if imageDetails.Tag != "" {
+		image = strings.Replace(image, colon+imageDetails.Tag, "", 1)
+	}
+	if imageDetails.Digest == "" {
+		if imageDetails.Tag != "" {
+			image = image + colon + imageDetails.Tag
+		}
+		digest, err := findDigestForImage(image)
+		if err != nil {
+			return "", err
+		}
+		if imageDetails.Tag != "" {
+			image = strings.TrimSuffix(image, colon+imageDetails.Tag)
+		}
+		image = image + atTheRate + digest
+	}
+	return image, nil
+}
+
+// getProjectIdFromImageName -  get project id from image name
+func getProjectIDFromImageName(image string) (string, error) {
+	imageSlice := strings.Split(image, "/")
+	if len(imageSlice) < 2 {
+		errMessage := fmt.Errorf(invalidImageReferenceMsg, image)
+		zap.S().Error(errMessage)
+		return "", errMessage
+	}
+	projectID := imageSlice[1]
+	return projectID, nil
+}
+
+//findDigestForImage - get digest from image name and tag
+func findDigestForImage(image string) (digest string, err error) {
+	zap.S().Debug("fetching digest for image %s", image)
+	var nameOpts []name.Option
+
+	ref, err := name.ParseReference(image, nameOpts...)
+	if err != nil {
+		zap.S().Errorf(invalidImageReferenceMsg, image)
+		return
+	}
+	domain := ref.Context().RegistryStr()
+
+	var remoteOpts []remote.Option
+
+	auth, err := getCredentials(image, domain)
+	if err != nil {
+		return
+	}
+	remoteOpts = append(remoteOpts, remote.WithAuth(&auth))
+
+	des, err := remote.Get(ref, remoteOpts...)
+	if err != nil {
+		errorMsg := fmt.Errorf(failToGetDigestMsg, image, err)
+		zap.S().Error(errorMsg)
+		return
+	}
+
+	img, err := des.Image()
+	if err != nil {
+		errorMsg := fmt.Errorf(failToGetDigestMsg, image, err)
+		zap.S().Error(errorMsg)
+		return
+	}
+
+	dig, err := img.Digest()
+	if err != nil {
+		errorMsg := fmt.Errorf(failToGetDigestMsg, image, err)
+		zap.S().Error(errorMsg)
+		return
+	}
+	digest = dig.String()
+	return
+}
+
+//getCredentials - get the credentials from the application key
+func getCredentials(image string, domain string) (auth authn.Basic, err error) {
+	gcpCredPath := os.Getenv(googlCredPath)
+	if gcpCredPath == "" {
+		errorMsg := fmt.Errorf(failToGetDigestMsg, image, err)
+		zap.S().Error(errorMsg)
+		err = errorMsg
+		return
+	}
+	credStore := store.NewGCRCredStore(gcpCredPath)
+
+	userCfg, err := config.LoadUserConfig()
+	if err != nil {
+		errorMsg := fmt.Errorf(failToGetDigestMsg, image, err)
+		zap.S().Error(errorMsg)
+		return
+	}
+	helper := credhelper.NewGCRCredentialHelper(credStore, userCfg)
+
+	username, password, err := helper.Get(domain)
+	if err != nil {
+		errorMsg := fmt.Errorf(failToGetDigestMsg, image, err)
+		zap.S().Error(errorMsg)
+		return
+	}
+
+	auth = authn.Basic{Username: username, Password: password}
+	return
+}
diff --git a/pkg/vulnerability/interface.go b/pkg/vulnerability/interface.go
new file mode 100644
index 000000000..535806017
--- /dev/null
+++ b/pkg/vulnerability/interface.go
@@ -0,0 +1,33 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+)
+
+//ContainerRegistry vulnerability Container Registry
+type ContainerRegistry interface {
+	checkRegistry(image string) bool
+	getVulnerabilities(output.ContainerDetails, map[string]interface{}) []output.Vulnerability
+}
+
+// Engine engine that holds methods for vulnerability operation
+type Engine interface {
+	FetchVulnerabilities(output.AllResourceConfigs, map[string]interface{}) output.AllResourceConfigs
+	ReportVulnerability(EngineInput, map[string]interface{}) EngineOutput
+}
diff --git a/pkg/vulnerability/types.go b/pkg/vulnerability/types.go
new file mode 100644
index 000000000..3e639fe89
--- /dev/null
+++ b/pkg/vulnerability/types.go
@@ -0,0 +1,104 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"encoding/xml"
+	"strings"
+
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+	"github.com/accurics/terrascan/pkg/results"
+	"github.com/google/go-containerregistry/pkg/name"
+	"go.uber.org/zap"
+)
+
+const (
+	colon           = ":"
+	slash           = "/"
+	defaultTagValue = "latest"
+	atTheRate       = "@"
+	sha256          = "sha256"
+)
+
+// VulEngine Implements the vulnerbaility engine interface
+type VulEngine struct {
+	results EngineOutput
+}
+
+// EngineInput holds input for vulnerability engine
+type EngineInput struct {
+	InputData *output.AllResourceConfigs
+}
+
+// EngineOutput Contains data output from the engine
+type EngineOutput struct {
+	XMLName                 xml.Name `json:"-" yaml:"-" xml:"results"`
+	*results.ViolationStore `json:"results" yaml:"results" xml:"results"`
+}
+
+//ImageDetails will hold details about the image being scanned for vulnerabilities.
+type ImageDetails struct {
+	Tag        string `json:"tag"`
+	Digest     string `json:"digest"`
+	Name       string `json:"name"`
+	Repository string `json:"repository"`
+	Registry   string `json:"registry"`
+}
+
+// GetImageDetails finds image component from image name
+func GetImageDetails(image string, imageDetails ImageDetails) ImageDetails {
+	base := image
+	imageSha256SplitToken := atTheRate + sha256 + colon
+	if strings.Contains(image, imageSha256SplitToken) {
+		parts := strings.Split(image, imageSha256SplitToken)
+		if len(parts) >= 2 {
+			base = strings.Join(parts[:len(parts)-1], "")
+			imageDetails.Digest = sha256 + colon + parts[len(parts)-1]
+		}
+		return GetImageDetails(base, imageDetails)
+	}
+	parts := strings.Split(image, colon)
+	if len(parts) > 1 && !strings.Contains(parts[len(parts)-1], slash) {
+		base = strings.Join(parts[:len(parts)-1], colon)
+		imageDetails.Tag = parts[len(parts)-1]
+	}
+
+	imageDetails.Repository = GetRepository(base)
+	imageDetails.Registry = strings.Split(image, slash+imageDetails.Repository)[0]
+	return imageDetails
+}
+
+// GetRepository finds repository from image name
+func GetRepository(image string) (repository string) {
+	parts := strings.SplitN(image, slash, 2)
+	if len(parts) == 2 && (strings.ContainsRune(parts[0], '.') || strings.ContainsRune(parts[0], ':')) {
+		repository = parts[1]
+	}
+	return
+}
+
+//GetDomain get image domain from image name
+func GetDomain(image string) string {
+	var nameOpts []name.Option
+	ref, err := name.ParseReference(image, nameOpts...)
+	if err != nil {
+		zap.S().Error(invalidImageReferenceMsg, image)
+		return ""
+	}
+	domain := ref.Context().RegistryStr()
+	return domain
+}
diff --git a/pkg/vulnerability/vulnerability.go b/pkg/vulnerability/vulnerability.go
new file mode 100644
index 000000000..90e6a1c97
--- /dev/null
+++ b/pkg/vulnerability/vulnerability.go
@@ -0,0 +1,133 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"strings"
+
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+	"github.com/accurics/terrascan/pkg/results"
+	"go.uber.org/zap"
+)
+
+var containerRegistry = make(map[string]ContainerRegistry)
+
+const (
+	//VulnerabilityCVSSSource hold type of cvss source
+	VulnerabilityCVSSSource = "nvd"
+)
+
+//RegisterContainerRegistry register the container registry for vulnerability scanning
+func RegisterContainerRegistry(registryType string, registry ContainerRegistry) {
+	containerRegistry[registryType] = registry
+}
+
+// NewVulEngine returns a new vulnerability engine
+func NewVulEngine() (*VulEngine, error) {
+
+	// vulnerability engine struct
+	engine := &VulEngine{}
+
+	// successful
+	return engine, nil
+}
+
+//FetchVulnerabilities fetch vulnerabilities for images found in IaC files
+func (v *VulEngine) FetchVulnerabilities(resourceConfigs output.AllResourceConfigs, options map[string]interface{}) output.AllResourceConfigs {
+	for i, congigs := range resourceConfigs {
+		for j, config := range congigs {
+			for k, container := range config.ContainerImages {
+				resourceConfigs[i][j].ContainerImages[k].Vulnerabilities =
+					append(resourceConfigs[i][j].ContainerImages[k].Vulnerabilities,
+						getVulnerabilitiesByRepository(container, options)...)
+			}
+			for l, container := range config.InitContainerImages {
+				resourceConfigs[i][j].InitContainerImages[l].Vulnerabilities =
+					append(resourceConfigs[i][j].InitContainerImages[l].Vulnerabilities,
+						getVulnerabilitiesByRepository(container, options)...)
+			}
+		}
+	}
+	return resourceConfigs
+}
+
+//getVulnerabilitiesByRepository get vulnerabilities depending on type of registry
+func getVulnerabilitiesByRepository(container output.ContainerDetails, options map[string]interface{}) []output.Vulnerability {
+	for _, registry := range containerRegistry {
+		if registry.checkRegistry(container.Image) {
+			return registry.getVulnerabilities(container, options)
+		}
+	}
+	zap.S().Debugf("no registered container registry found for image %s", container.Image)
+	return []output.Vulnerability{}
+}
+
+// ReportVulnerability Add a vulnrability for a given resource in scan summary
+func (v *VulEngine) ReportVulnerability(engineInput EngineInput, options map[string]interface{}) EngineOutput {
+	v.results.ViolationStore = results.NewViolationStore()
+	for _, resources := range *engineInput.InputData {
+		for _, resource := range resources {
+			for _, container := range resource.ContainerImages {
+				vulnerabilities := prepareVulnerabilityObject(container, resource, options)
+				v.results.ViolationStore.Vulnerabilities =
+					append(v.results.ViolationStore.Vulnerabilities, vulnerabilities...)
+
+			}
+			for _, container := range resource.InitContainerImages {
+				vulnerabilities := prepareVulnerabilityObject(container, resource, options)
+				v.results.ViolationStore.Vulnerabilities =
+					append(v.results.ViolationStore.Vulnerabilities, vulnerabilities...)
+			}
+		}
+	}
+	count := len(v.results.ViolationStore.Vulnerabilities)
+	v.results.Summary.Vulnerabilities = &count
+	return v.results
+}
+
+// prepareVulnerabilityObject Add a vulnrability for a given resource
+func prepareVulnerabilityObject(container output.ContainerDetails, resource output.ResourceConfig, options map[string]interface{}) []*results.Vulnerability {
+	vulnerabilities := []*results.Vulnerability{}
+	for _, vul := range container.Vulnerabilities {
+		vulnerability := &results.Vulnerability{
+			Image:            container.Image,
+			Container:        container.Name,
+			Package:          vul.PkgName,
+			Severity:         strings.ToUpper(vul.Severity),
+			VulnerabilityID:  vul.VulnerabilityID,
+			Description:      vul.Description,
+			InstalledVersion: vul.InstalledVersion,
+			File:             resource.Source,
+			LineNumber:       resource.Line,
+			PrimaryURL:       vul.PrimaryURL,
+			ResourceType:     resource.Type,
+			ResourceName:     resource.Name,
+		}
+		if cvss, ok := vul.CVSS[VulnerabilityCVSSSource]; ok {
+			vulnerability.CVSSScore = results.CVSS{
+				V2Vector: cvss.V2Vector,
+				V2Score:  cvss.V2Score,
+				V3Vector: cvss.V3Vector,
+				V3Score:  cvss.V3Score,
+			}
+		}
+		vulnerabilities = append(vulnerabilities, vulnerability)
+	}
+
+	return vulnerabilities
+
+}
diff --git a/pkg/writer/human_readable.go b/pkg/writer/human_readable.go
index fc5605b32..d19fe7616 100644
--- a/pkg/writer/human_readable.go
+++ b/pkg/writer/human_readable.go
@@ -59,6 +59,13 @@ Skipped Violations -
 	-----------------------------------------------------------------------
 	{{end}}
 {{end}}
+{{- if (gt (len .ViolationStore.Vulnerabilities) 0) }}
+Vulnerabilities Details - 
+    {{range $index, $element := .ViolationStore.Vulnerabilities}}
+	{{defaultVulnerabilities $element | printf "%s"}}
+	-----------------------------------------------------------------------
+	{{end}}
+{{end}}
 Scan Summary -
 
 	{{scanSummary .ViolationStore.Summary | printf "%s"}}
@@ -72,10 +79,11 @@ func init() {
 // HumanReadbleWriter display scan summary in human readable format
 func HumanReadbleWriter(data interface{}, writer io.Writer) error {
 	tmpl, err := template.New("Report").Funcs(template.FuncMap{
-		"defaultViolations":  defaultViolations,
-		"detailedViolations": detailedViolations,
-		"scanSummary":        scanSummary,
-		"passedRules":        passedRules,
+		"defaultViolations":      defaultViolations,
+		"detailedViolations":     detailedViolations,
+		"scanSummary":            scanSummary,
+		"passedRules":            passedRules,
+		"defaultVulnerabilities": defaultVulnerabilities,
 	}).Parse(defaultTemplate)
 	if err != nil {
 		zap.S().Errorf("failed to write human readable output. error: '%v'", err)
@@ -144,6 +152,11 @@ func scanSummary(s results.ScanSummary) string {
 		"Low", s.LowCount,
 		"Medium", s.MediumCount,
 		"High", s.HighCount)
+
+	if s.Vulnerabilities != nil {
+		out += fmt.Sprintf("%-20v:\t%d\n\t", "Vulnerabilities", *s.Vulnerabilities)
+	}
+
 	return out
 }
 
@@ -156,3 +169,22 @@ func passedRules(v results.PassedRule) string {
 		"Category", v.Category)
 	return out
 }
+
+func defaultVulnerabilities(v results.Vulnerability) string {
+	resourceName := v.ResourceName
+	// print "" when as resource name value when it is empty
+	if resourceName == "" {
+		resourceName = `""`
+	}
+	out := fmt.Sprintf("%-20v:\t%s\n\t%-20v:\t%s\n\t%-20v:\t%s\n\t%-20v:\t%s\n\t%-20v:\t%s\n\t%-20v:\t%s\n\t%-20v:\t%d\n\t%-20v:\t%s\n\t%-20v:\t%s\n\t",
+		"Description", v.Description,
+		"Vulnerability ID", v.VulnerabilityID,
+		"Resource Name", resourceName,
+		"Resource Type", v.ResourceType,
+		"Image", v.Image,
+		"Package", v.Package,
+		"Line", v.LineNumber,
+		"Primary URL", v.PrimaryURL,
+		"Primary URL", v.Severity)
+	return out
+}


Test patch:
diff --git a/pkg/http-server/file-scan_test.go b/pkg/http-server/file-scan_test.go
index 7c5913fad..771e8c412 100644
--- a/pkg/http-server/file-scan_test.go
+++ b/pkg/http-server/file-scan_test.go
@@ -25,21 +25,23 @@ func TestUpload(t *testing.T) {
 	testCategories := []string{"COMPLIANCE VALIDATION", "DATA PROTECTION"}
 
 	table := []struct {
-		name              string
-		path              string
-		param             string
-		iacType           string
-		iacVersion        string
-		cloudType         string
-		scanRules         []string
-		skipRules         []string
-		severity          string
-		configOnly        bool
-		invalidConfigOnly bool
-		showPassed        bool
-		invalidShowPassed bool
-		wantStatus        int
-		categories        []string
+		name                       string
+		path                       string
+		param                      string
+		iacType                    string
+		iacVersion                 string
+		cloudType                  string
+		scanRules                  []string
+		skipRules                  []string
+		severity                   string
+		configOnly                 bool
+		invalidConfigOnly          bool
+		showPassed                 bool
+		invalidShowPassed          bool
+		wantStatus                 int
+		categories                 []string
+		invalidFindVulnerabilities bool
+		findVulnerabilities        bool
 	}{
 		{
 			name:       "valid file scan",
@@ -249,6 +251,15 @@ func TestUpload(t *testing.T) {
 			cloudType:  testCloudType,
 			wantStatus: http.StatusOK,
 		},
+		{
+			name:                       "test for invalid value find vulnerability",
+			path:                       testFilePath,
+			param:                      testParamName,
+			iacType:                    testIacType,
+			cloudType:                  testCloudType,
+			wantStatus:                 http.StatusBadRequest,
+			invalidFindVulnerabilities: true,
+		},
 	}
 
 	for _, tt := range table {
@@ -329,6 +340,18 @@ func TestUpload(t *testing.T) {
 				}
 			}
 
+			if !tt.invalidFindVulnerabilities {
+				if err = writer.WriteField("find_vulnerabilities", strconv.FormatBool(tt.findVulnerabilities)); err != nil {
+					writer.Close()
+					t.Error(err)
+				}
+			} else {
+				if err = writer.WriteField("find_vulnerabilities", "invalid"); err != nil {
+					writer.Close()
+					t.Error(err)
+				}
+			}
+
 			writer.Close()
 
 			// http request of the type "/v1/{iacType}/{iacVersion}/{cloudType}/file/scan"
diff --git a/pkg/iac-providers/kubernetes/v1/extract-images_test.go b/pkg/iac-providers/kubernetes/v1/extract-images_test.go
index 1df393ed3..838dc0ed6 100644
--- a/pkg/iac-providers/kubernetes/v1/extract-images_test.go
+++ b/pkg/iac-providers/kubernetes/v1/extract-images_test.go
@@ -34,8 +34,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 		name                       string
 		k                          *K8sV1
 		args                       args
-		wantContainerImageList     []output.ContainerNameAndImage
-		wantInitContainerImageList []output.ContainerNameAndImage
+		wantContainerImageList     []output.ContainerDetails
+		wantInitContainerImageList []output.ContainerDetails
 		wantErr                    bool
 	}{
 		{
@@ -45,8 +45,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				kind: "CRD",
 			},
 			wantErr:                    true,
-			wantContainerImageList:     []output.ContainerNameAndImage{},
-			wantInitContainerImageList: []output.ContainerNameAndImage{},
+			wantContainerImageList:     []output.ContainerDetails{},
+			wantInitContainerImageList: []output.ContainerDetails{},
 		},
 		{
 			name: "pod json document object",
@@ -57,8 +57,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "Pod",
 			},
-			wantContainerImageList:     []output.ContainerNameAndImage{{Name: "healthz", Image: "k8s.gcr.io/exechealthz-amd64:1.2"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{},
+			wantContainerImageList:     []output.ContainerDetails{{Name: "healthz", Image: "k8s.gcr.io/exechealthz-amd64:1.2"}},
+			wantInitContainerImageList: []output.ContainerDetails{},
 		},
 		{
 			name: "pod yaml document object",
@@ -69,8 +69,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "Pod",
 			},
-			wantContainerImageList:     []output.ContainerNameAndImage{{Name: "myapp-container", Image: "nginx"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{{Name: "myapp-container", Image: "busybox"}},
+			wantContainerImageList:     []output.ContainerDetails{{Name: "myapp-container", Image: "nginx"}},
+			wantInitContainerImageList: []output.ContainerDetails{{Name: "myapp-container", Image: "busybox"}},
 		},
 		{
 			name: "cronjob yaml document object",
@@ -81,8 +81,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "CronJob",
 			},
-			wantContainerImageList:     []output.ContainerNameAndImage{{Name: "hello", Image: "busybox"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{},
+			wantContainerImageList:     []output.ContainerDetails{{Name: "hello", Image: "busybox"}},
+			wantInitContainerImageList: []output.ContainerDetails{},
 		},
 		{
 			name: "job yaml document object",
@@ -93,8 +93,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "Job",
 			},
-			wantContainerImageList:     []output.ContainerNameAndImage{{Name: "c", Image: "gcr.io/terrascan/job-wq-1"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{},
+			wantContainerImageList:     []output.ContainerDetails{{Name: "c", Image: "gcr.io/terrascan/job-wq-1"}},
+			wantInitContainerImageList: []output.ContainerDetails{},
 		},
 		{
 			name: "deployment yaml document object",
@@ -105,8 +105,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "Deployment",
 			},
-			wantContainerImageList:     []output.ContainerNameAndImage{{Name: "nginx", Image: "nginx:1.14.2"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{{Name: "init", Image: "busybox"}},
+			wantContainerImageList:     []output.ContainerDetails{{Name: "nginx", Image: "nginx:1.14.2"}},
+			wantInitContainerImageList: []output.ContainerDetails{{Name: "init", Image: "busybox"}},
 		},
 		{
 			name: "daemonset yaml document object",
@@ -117,8 +117,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "DaemonSet",
 			},
-			wantContainerImageList:     []output.ContainerNameAndImage{{Name: "fluentd-elasticsearch", Image: "quay.io/fluentd_elasticsearch/fluentd:v2.5.2"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{},
+			wantContainerImageList:     []output.ContainerDetails{{Name: "fluentd-elasticsearch", Image: "quay.io/fluentd_elasticsearch/fluentd:v2.5.2"}},
+			wantInitContainerImageList: []output.ContainerDetails{},
 		},
 		{
 			name: "replicaset yaml document object",
@@ -129,8 +129,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "ReplicaSet",
 			},
-			wantContainerImageList:     []output.ContainerNameAndImage{{Name: "php-redis", Image: "gcr.io/google_samples/gb-frontend:v3"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{},
+			wantContainerImageList:     []output.ContainerDetails{{Name: "php-redis", Image: "gcr.io/google_samples/gb-frontend:v3"}},
+			wantInitContainerImageList: []output.ContainerDetails{},
 		},
 		{
 			name: "replicationcontroller yaml document object",
@@ -141,11 +141,11 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "ReplicationController",
 			},
-			wantContainerImageList: []output.ContainerNameAndImage{
+			wantContainerImageList: []output.ContainerDetails{
 				{Name: "nginx", Image: "nginx:latest"},
 				{Name: "sidecar1", Image: "sidecar-image-1"},
 				{Name: "sidecar2", Image: "sidecar-image-2"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{
+			wantInitContainerImageList: []output.ContainerDetails{
 				{Name: "init1", Image: "init-image-1"},
 				{Name: "init2", Image: "init-image-2"},
 				{Name: "init3", Image: "init-image-3"}},
@@ -159,8 +159,8 @@ func TestK8sV1ExtractContainerImages(t *testing.T) {
 				},
 				kind: "StatefulSet",
 			},
-			wantContainerImageList:     []output.ContainerNameAndImage{{Name: "nginx", Image: "k8s.gcr.io/nginx-slim:0.8"}},
-			wantInitContainerImageList: []output.ContainerNameAndImage{},
+			wantContainerImageList:     []output.ContainerDetails{{Name: "nginx", Image: "k8s.gcr.io/nginx-slim:0.8"}},
+			wantInitContainerImageList: []output.ContainerDetails{},
 		},
 	}
 	for _, tt := range tests {
diff --git a/pkg/iac-providers/kubernetes/v1/normalize_test.go b/pkg/iac-providers/kubernetes/v1/normalize_test.go
index bc28a2d5e..930de9c1e 100644
--- a/pkg/iac-providers/kubernetes/v1/normalize_test.go
+++ b/pkg/iac-providers/kubernetes/v1/normalize_test.go
@@ -238,8 +238,8 @@ func TestK8sV1Normalize(t *testing.T) {
 					},
 				},
 				SkipRules:           []output.SkipRule{testSkipRule},
-				ContainerImages:     []output.ContainerNameAndImage{{Name: "myapp-container", Image: "busybox"}},
-				InitContainerImages: []output.ContainerNameAndImage{},
+				ContainerImages:     []output.ContainerDetails{{Name: "myapp-container", Image: "busybox"}},
+				InitContainerImages: []output.ContainerDetails{},
 			},
 		},
 		{
@@ -274,8 +274,8 @@ func TestK8sV1Normalize(t *testing.T) {
 					},
 				},
 				SkipRules:           []output.SkipRule{testSkipRule},
-				ContainerImages:     []output.ContainerNameAndImage{},
-				InitContainerImages: []output.ContainerNameAndImage{},
+				ContainerImages:     []output.ContainerDetails{},
+				InitContainerImages: []output.ContainerDetails{},
 			},
 		},
 	}
diff --git a/pkg/iac-providers/output/vulnerability_test.go b/pkg/iac-providers/output/vulnerability_test.go
new file mode 100644
index 000000000..0c37bbb6f
--- /dev/null
+++ b/pkg/iac-providers/output/vulnerability_test.go
@@ -0,0 +1,312 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package output
+
+import (
+	"reflect"
+	"testing"
+
+	"github.com/aws/aws-sdk-go/service/ecr"
+	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
+)
+
+func TestCVSSPrepareFromECRImageScanAttribute(t *testing.T) {
+	v2VectorKey := ecrCvss + "2_" + ecrCvssVector
+	v2ScoreKey := ecrCvss + "2_" + ecrCvssScore
+	v3VectorKey := ecrCvss + "3_" + ecrCvssVector
+	v3ScoreKey := ecrCvss + "3_" + ecrCvssScore
+	value := "6.7"
+
+	type args struct {
+		attribute *ecr.Attribute
+	}
+	tests := []struct {
+		name string
+		args args
+		want *CVSS
+	}{
+		{
+			name: "v2 vector present in cvss object",
+			args: args{
+				attribute: &ecr.Attribute{
+					Key:   &v2VectorKey,
+					Value: &value,
+				},
+			},
+			want: &CVSS{
+				V2Vector: "6.7",
+			},
+		},
+		{
+			name: "v2 score present in cvss object",
+			args: args{
+				attribute: &ecr.Attribute{
+					Key:   &v2ScoreKey,
+					Value: &value,
+				},
+			},
+			want: &CVSS{
+				V2Score: 6.7,
+			},
+		},
+		{
+			name: "v3 score present in cvss object",
+			args: args{
+				attribute: &ecr.Attribute{
+					Key:   &v3ScoreKey,
+					Value: &value,
+				},
+			},
+			want: &CVSS{
+				V3Score: 6.7,
+			},
+		},
+		{
+			name: "v3 vector present in cvss object",
+			args: args{
+				attribute: &ecr.Attribute{
+					Key:   &v3VectorKey,
+					Value: &value,
+				},
+			},
+			want: &CVSS{
+				V3Vector: "6.7",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			cvss := &CVSS{}
+			cvss.PrepareFromECRImageScanAttribute(tt.args.attribute)
+			if !reflect.DeepEqual(cvss, tt.want) {
+				t.Errorf("PrepareFromECRImageScanAttribute() got = %v, want %v", cvss, tt.want)
+				return
+			}
+		})
+	}
+}
+
+func TestVulnerabilityPrepareFromECRImageScan(t *testing.T) {
+
+	name := "test_vulnerability"
+	severity := "low"
+	description := "description"
+	uri := ""
+	packageName := "test_package"
+	packageNameKey := ecrPackageName
+	packageVersion := "v1"
+	packageVersionKey := ecrPackageVersion
+	v3ScoreKey := ecrCvss + "3_" + ecrCvssScore
+	value := "6.7"
+
+	type args struct {
+		imageScanFinding *ecr.ImageScanFinding
+	}
+	tests := []struct {
+		name string
+		args args
+		want *Vulnerability
+	}{
+		{
+			name: "get Vulnerability object ready",
+			args: args{
+				imageScanFinding: &ecr.ImageScanFinding{
+					Description: &description,
+					Name:        &name,
+					Severity:    &severity,
+					Uri:         &uri,
+					Attributes: []*ecr.Attribute{
+						{
+							Key:   &packageNameKey,
+							Value: &packageName,
+						},
+						{
+							Key:   &packageVersionKey,
+							Value: &packageVersion,
+						},
+						{
+							Key:   &v3ScoreKey,
+							Value: &value,
+						},
+						{
+							Key:   nil,
+							Value: nil,
+						},
+					},
+				},
+			},
+			want: &Vulnerability{
+				VulnerabilityID:  "test_vulnerability",
+				PkgName:          "test_package",
+				InstalledVersion: "v1",
+				PrimaryURL:       "https://cve.mitre.org/cgi-bin/cvename.cgi?name=test_vulnerability",
+				Description:      "description",
+				Severity:         "LOW",
+				CVSS: VendorCVSS{
+					"nvd": CVSS{
+						V3Score: 6.7,
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &Vulnerability{}
+			v.PrepareFromECRImageScan(tt.args.imageScanFinding)
+			if !reflect.DeepEqual(v, tt.want) {
+				t.Errorf("PrepareFromECRImageScan() got = %v, want %v", v, tt.want)
+				return
+			}
+		})
+	}
+}
+
+func TestVulnerabilityPrepareFromACRImageScan(t *testing.T) {
+	type args struct {
+		acrResponse ACRResponse
+	}
+	tests := []struct {
+		name string
+		args args
+		want *Vulnerability
+	}{
+		{
+			name: "vulnerability not found",
+			args: args{
+				acrResponse: ACRResponse{},
+			},
+			want: &Vulnerability{},
+		},
+		{
+			name: "vulnerability object from acr response",
+			args: args{
+				acrResponse: ACRResponse{
+					Properties: ACRVulnerabilityConfig{
+						ID:          "test_ID",
+						Description: "description",
+						AdditionalData: ACRAdditionalData{
+							Cve: []ACRCve{
+								{
+									Title: "test_Title",
+									Link:  "",
+								},
+							},
+							Cvss: ACRCvss{
+								V2: ACRCvssBase{
+									Base: 4.5,
+								},
+								V3: ACRCvssBase{
+									Base: 4.5,
+								},
+							},
+						},
+						Status: ACRStatus{
+							Severity: "low",
+						},
+					},
+				},
+			},
+			want: &Vulnerability{
+				VulnerabilityID: "test_Title",
+				PrimaryURL:      "https://cve.mitre.org/cgi-bin/cvename.cgi?name=test_Title",
+				Description:     "description",
+				Severity:        "LOW",
+				CVSS: VendorCVSS{
+					"nvd": CVSS{V2Score: 4.5, V3Score: 4.5}}},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &Vulnerability{}
+			v.PrepareFromACRImageScan(tt.args.acrResponse)
+			if !reflect.DeepEqual(v, tt.want) {
+				t.Errorf("PrepareFromACRImageScan() got = %v, want %v", v, tt.want)
+				return
+			}
+		})
+	}
+}
+
+func TestVulnerabilityPrepareFromGCRImageScan(t *testing.T) {
+
+	type args struct {
+		gcpVulnerability *grafeaspb.Occurrence
+	}
+	tests := []struct {
+		name string
+		args args
+		want *Vulnerability
+	}{
+		{
+			name: "complete vulnerability object",
+			args: args{
+				gcpVulnerability: &grafeaspb.Occurrence{
+					NoteName: "https://test/CVE-1234",
+					Details: &grafeaspb.Occurrence_Vulnerability{
+						Vulnerability: &grafeaspb.VulnerabilityOccurrence{
+							Severity:  2,
+							CvssScore: 3.3,
+							Type:      "os",
+							PackageIssue: []*grafeaspb.VulnerabilityOccurrence_PackageIssue{
+								{
+									AffectedPackage: "test",
+									AffectedVersion: &grafeaspb.Version{
+										FullName: "v1.4.3",
+									},
+									FixedVersion: &grafeaspb.Version{
+										FullName: "v1.4.3",
+									},
+								},
+							},
+							LongDescription:  "long description",
+							ShortDescription: "short description",
+							RelatedUrls: []*grafeaspb.RelatedUrl{
+								{
+									Url: "http://test_url",
+								},
+							},
+						},
+					},
+				},
+			},
+			want: &Vulnerability{
+				Type:             "os",
+				VulnerabilityID:  "CVE-1234",
+				PkgName:          "test",
+				InstalledVersion: "v1.4.3",
+				FixedVersion:     "v1.4.3",
+				PrimaryURL:       "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-1234",
+				Description:      "long description",
+				Severity:         "LOW",
+				CVSS: VendorCVSS{
+					"nvd": CVSS{V2Score: 3.299999952316284}},
+				References: []string{"http://test_url"},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &Vulnerability{}
+			v.PrepareFromGCRImageScan(tt.args.gcpVulnerability)
+			if !reflect.DeepEqual(v, tt.want) {
+				t.Errorf("PrepareFromGCRImageScan() got = %v, want %v", v, tt.want)
+				return
+			}
+		})
+	}
+}
diff --git a/pkg/runtime/executor_test.go b/pkg/runtime/executor_test.go
index dfce69d1b..2d8d65ec2 100644
--- a/pkg/runtime/executor_test.go
+++ b/pkg/runtime/executor_test.go
@@ -17,12 +17,16 @@
 package runtime
 
 import (
+	"encoding/xml"
 	"fmt"
 	"path/filepath"
 	"reflect"
 	"testing"
 
 	tfv15 "github.com/accurics/terrascan/pkg/iac-providers/terraform/v15"
+	"github.com/accurics/terrascan/pkg/results"
+	"github.com/accurics/terrascan/pkg/vulnerability"
+	"github.com/hashicorp/go-multierror"
 
 	iacProvider "github.com/accurics/terrascan/pkg/iac-providers"
 	armv1 "github.com/accurics/terrascan/pkg/iac-providers/arm/v1"
@@ -34,7 +38,6 @@ import (
 	tfv12 "github.com/accurics/terrascan/pkg/iac-providers/terraform/v12"
 	tfv14 "github.com/accurics/terrascan/pkg/iac-providers/terraform/v14"
 	"github.com/accurics/terrascan/pkg/notifications/webhook"
-	"github.com/hashicorp/go-multierror"
 
 	"github.com/accurics/terrascan/pkg/config"
 	"github.com/accurics/terrascan/pkg/iac-providers/output"
@@ -71,6 +74,9 @@ func (m MockIacProvider) LoadIacFile(file string, options map[string]interface{}
 type MockPolicyEngine struct {
 	err error
 }
+type MockVulnerabiltyEngine struct {
+	out vulnerability.EngineOutput
+}
 
 func (m MockPolicyEngine) Init(input string, filter policy.PreLoadFilter) error {
 	return m.err
@@ -90,6 +96,14 @@ func (m MockPolicyEngine) Evaluate(input policy.EngineInput, filter policy.PreSc
 	return out, m.err
 }
 
+func (m MockVulnerabiltyEngine) ReportVulnerability(input vulnerability.EngineInput, options map[string]interface{}) (out vulnerability.EngineOutput) {
+	return m.out
+}
+
+func (m MockVulnerabiltyEngine) FetchVulnerabilities(input output.AllResourceConfigs, options map[string]interface{}) (out output.AllResourceConfigs) {
+	return out
+}
+
 func (m MockPolicyEngine) GetResults() (out policy.EngineOutput) {
 	return out
 }
@@ -177,6 +191,22 @@ func TestExecute(t *testing.T) {
 			},
 			wantErr: errMockPolicyEngine,
 		},
+		{
+			name: "test find vulnerability engine",
+			executor: Executor{
+				iacProviders:  []iacProvider.IacProvider{MockIacProvider{err: nil}},
+				notifiers:     []notifications.Notifier{&MockNotifier{err: nil}},
+				policyEngines: []policy.Engine{MockPolicyEngine{err: nil}},
+				vulnerabilityEngine: MockVulnerabiltyEngine{
+					out: vulnerability.EngineOutput{
+						XMLName:        xml.Name{},
+						ViolationStore: results.NewViolationStore(),
+					},
+				},
+				findVulnerabilities: true,
+			},
+			wantErr: nil,
+		},
 	}
 
 	for _, tt := range table {
@@ -557,7 +587,7 @@ func TestNewExecutor(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			config.LoadGlobalConfig(tt.configfile)
 
-			gotExecutor, gotErr := NewExecutor(tt.flags.iacType, tt.flags.iacVersion, tt.flags.policyTypes, tt.flags.filePath, tt.flags.dirPath, tt.flags.policyPath, tt.flags.scanRules, tt.flags.skipRules, tt.flags.categories, tt.flags.severity, false, false)
+			gotExecutor, gotErr := NewExecutor(tt.flags.iacType, tt.flags.iacVersion, tt.flags.policyTypes, tt.flags.filePath, tt.flags.dirPath, tt.flags.policyPath, tt.flags.scanRules, tt.flags.skipRules, tt.flags.categories, tt.flags.severity, false, false, false)
 
 			if !reflect.DeepEqual(tt.wantErr, gotErr) {
 				t.Errorf("Mismatch in error => got: '%v', want: '%v'", gotErr, tt.wantErr)
diff --git a/pkg/vulnerability/acr_test.go b/pkg/vulnerability/acr_test.go
new file mode 100644
index 000000000..80833f42e
--- /dev/null
+++ b/pkg/vulnerability/acr_test.go
@@ -0,0 +1,442 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"context"
+	"fmt"
+	"reflect"
+	"testing"
+
+	"github.com/Azure/azure-sdk-for-go/profiles/preview/preview/containerregistry/runtime/containerregistry"
+	"github.com/Azure/azure-sdk-for-go/services/resourcegraph/mgmt/2021-03-01/resourcegraph"
+	"github.com/Azure/go-autorest/autorest"
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+)
+
+type mockScanner struct {
+	basicAuthorizer *autorest.BasicAuthorizer
+	queryError      error
+	authorizerError error
+	attributesError error
+	authorizer      autorest.Authorizer
+	tagClient       containerregistry.TagClient
+	queryResponse   resourcegraph.QueryResponse
+	attributes      containerregistry.TagAttributes
+	validImage      bool
+	digest          string
+}
+
+//newTagClient
+func (m mockScanner) newTagClient(loginURL string) containerregistry.TagClient {
+	return m.tagClient
+}
+
+//newBasicAuthorizer
+func (m mockScanner) newBasicAuthorizer(username string, password string) *autorest.BasicAuthorizer {
+	return m.basicAuthorizer
+}
+
+//newAuthorizerFromFile
+func (m mockScanner) newAuthorizerFromFile() (autorest.Authorizer, error) {
+	return m.authorizer, m.authorizerError
+}
+
+//newResourcegraphClient
+func (mockScanner) newResourcegraphClient() resourcegraph.BaseClient {
+	return resourcegraph.New()
+}
+
+//getResources
+func (m mockScanner) getResources(ctx context.Context, request resourcegraph.QueryRequest, client resourcegraph.BaseClient) (resourcegraph.QueryResponse, error) {
+	return m.queryResponse, m.queryError
+}
+
+//GetAttributes
+func (m mockScanner) getAttributes(ctx context.Context, name string, reference string, client containerregistry.TagClient) (result containerregistry.TagAttributes, err error) {
+	return m.attributes, m.attributesError
+}
+
+func TestScanImage(t *testing.T) {
+	type fields struct {
+		scanner acrScanner
+	}
+	type args struct {
+		image string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    []output.ACRResponse
+		wantErr error
+	}{
+		{
+			name: "error getting authorizer",
+			fields: fields{
+				scanner: mockScanner{
+					authorizer:      nil,
+					authorizerError: fmt.Errorf("error creating authorizer"),
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx:latest@sha256:3f13b4376446cf92b0cb9a5c46ba75d57",
+			},
+			want:    []output.ACRResponse{},
+			wantErr: fmt.Errorf("error creating authorizer"),
+		},
+		{
+			name: "invalid image",
+			fields: fields{
+				scanner: mockScanner{
+					authorizer: nil,
+					validImage: false,
+				},
+			},
+			args: args{
+				image: "test",
+			},
+			want:    []output.ACRResponse{},
+			wantErr: fmt.Errorf("invalid image reference test "),
+		},
+		{
+			name: "error from query execution",
+			fields: fields{
+				scanner: mockScanner{
+					queryError: fmt.Errorf("error finding resource"),
+					validImage: true,
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx:latest@sha256:3f13b4376446cf92b0cb9a5c46ba75d57",
+			},
+			want:    []output.ACRResponse{},
+			wantErr: fmt.Errorf("error finding resource"),
+		},
+		{
+			name: "unmarshal error",
+			fields: fields{
+				scanner: mockScanner{
+					queryError: nil,
+					validImage: true,
+					queryResponse: resourcegraph.QueryResponse{
+						Data: "nil",
+					},
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx:latest@sha256:3f13b4376446cf92b0cb9a5c46ba75d57",
+			},
+			want:    []output.ACRResponse{},
+			wantErr: fmt.Errorf("error unmarshaling image %s scan results", "test.azurecr.io/nginx:latest@sha256:3f13b4376446cf92b0cb9a5c46ba75d57"),
+		},
+		{
+			name: "marshal error",
+			fields: fields{
+				scanner: mockScanner{
+					queryError: nil,
+					validImage: true,
+					queryResponse: resourcegraph.QueryResponse{
+						Data: make(chan int),
+					},
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx:latest@sha256:3f13b4376446cf92b0cb9a5c46ba75d57",
+			},
+			want:    []output.ACRResponse{},
+			wantErr: fmt.Errorf("error marshaling image %s scan results", "test.azurecr.io/nginx:latest@sha256:3f13b4376446cf92b0cb9a5c46ba75d57"),
+		},
+		{
+			name: "valid response from query execution",
+			fields: fields{
+				scanner: mockScanner{
+					queryError: nil,
+					validImage: true,
+					queryResponse: resourcegraph.QueryResponse{
+						Data: []output.ACRResponse{{
+							Properties: output.ACRVulnerabilityConfig{
+								ID: "test",
+							},
+						}},
+					},
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx:latest@sha256:3f13b4376446cf92b0cb9a5c46ba75d57",
+			},
+			want: []output.ACRResponse{
+				{
+					Properties: output.ACRVulnerabilityConfig{
+						ID: "test",
+					},
+				},
+			},
+			wantErr: nil,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			a := &ACR{
+				scanner: tt.fields.scanner,
+			}
+			got, err := a.ScanImage(tt.args.image)
+			if !reflect.DeepEqual(err, tt.wantErr) {
+				t.Errorf("ACR.ScanImage() got error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ACR.ScanImage() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetACRImageDetails(t *testing.T) {
+	digest := "sha256:3f13b4376446cf92b0cb9a"
+	type fields struct {
+		scanner acrScanner
+	}
+	type args struct {
+		image     string
+		authrizer autorest.Authorizer
+	}
+	tests := []struct {
+		name             string
+		fields           fields
+		args             args
+		wantImageDetails ImageDetails
+		wantValidImage   bool
+	}{
+		{
+			name: "invalid image",
+			fields: fields{
+				scanner: nil,
+			},
+			args: args{
+				image: "test",
+			},
+			wantImageDetails: ImageDetails{
+				Registry: "test",
+			},
+			wantValidImage: false,
+		},
+		{
+			name: "unable to find image digest",
+			fields: fields{
+				scanner: mockScanner{
+					digest: "",
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx",
+			},
+			wantImageDetails: ImageDetails{
+				Registry:   "test.azurecr.io",
+				Repository: "nginx",
+				Tag:        "latest",
+			},
+			wantValidImage: false,
+		},
+		{
+			name: "found image digest",
+			fields: fields{
+				scanner: mockScanner{
+					digest: "sha256:3f13b4376446cf92b0cb9a",
+					attributes: containerregistry.TagAttributes{
+						Attributes: &containerregistry.TagAttributesBase{
+							Digest: &digest,
+						},
+					},
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx",
+			},
+			wantImageDetails: ImageDetails{
+				Registry:   "test.azurecr.io",
+				Repository: "nginx",
+				Tag:        "latest",
+				Digest:     "sha256:3f13b4376446cf92b0cb9a",
+			},
+			wantValidImage: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			a := &ACR{
+				scanner: tt.fields.scanner,
+			}
+			gotImageDetails, gotValidImage := a.getACRImageDetails(tt.args.image, tt.args.authrizer)
+			if !reflect.DeepEqual(gotImageDetails, tt.wantImageDetails) {
+				t.Errorf("ACR.getACRImageDetails() gotImageDetails = %v, want %v", gotImageDetails, tt.wantImageDetails)
+			}
+			if gotValidImage != tt.wantValidImage {
+				t.Errorf("ACR.getACRImageDetails() gotValidImage = %v, want %v", gotValidImage, tt.wantValidImage)
+			}
+		})
+	}
+}
+
+func TestGetImageDigestFromTag(t *testing.T) {
+	digest := "sha256:3f13b4376446cf92b0cb9a"
+	type fields struct {
+		scanner acrScanner
+	}
+	type args struct {
+		image        string
+		imageDetails ImageDetails
+		loginURL     string
+	}
+	tests := []struct {
+		name       string
+		fields     fields
+		args       args
+		wantDigest string
+	}{
+		{
+			name: "error getting digest",
+			fields: fields{
+				scanner: mockScanner{
+					attributesError: fmt.Errorf("error getting image attributes"),
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx:latest",
+				imageDetails: ImageDetails{
+					Registry:   "test.azurecr.io",
+					Repository: "nginx",
+					Tag:        "latest",
+				},
+				loginURL: "https://test.azurecr.io",
+			},
+			wantDigest: "",
+		},
+		{
+			name: "digest found",
+			fields: fields{
+				scanner: mockScanner{
+					attributes: containerregistry.TagAttributes{
+						Attributes: &containerregistry.TagAttributesBase{
+							Digest: &digest,
+						},
+					},
+				},
+			},
+			args: args{
+				image: "test.azurecr.io/nginx:latest",
+				imageDetails: ImageDetails{
+					Registry:   "test.azurecr.io",
+					Repository: "nginx",
+					Tag:        "latest",
+				},
+				loginURL: "https://test.azurecr.io",
+			},
+			wantDigest: digest,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			a := &ACR{
+				scanner: tt.fields.scanner,
+			}
+			if gotDigest := a.getImageDigestFromTag(tt.args.image, tt.args.imageDetails, tt.args.loginURL); gotDigest != tt.wantDigest {
+				t.Errorf("ACR.getImageDigestFromTag() = %v, want %v", gotDigest, tt.wantDigest)
+			}
+		})
+	}
+}
+
+func TestGetVulnerabilities(t *testing.T) {
+	type fields struct {
+		scanner acrScanner
+	}
+	type args struct {
+		container output.ContainerDetails
+		options   map[string]interface{}
+	}
+	tests := []struct {
+		name                string
+		fields              fields
+		args                args
+		wantVulnerabilities []output.Vulnerability
+	}{
+		{
+			name: "error scanning image",
+			args: args{
+				container: output.ContainerDetails{
+					Image: "test",
+				},
+			},
+			fields: fields{
+				scanner: mockScanner{
+					authorizer:      nil,
+					authorizerError: fmt.Errorf("error creating authorizer"),
+				},
+			},
+			wantVulnerabilities: nil,
+		},
+		{
+			name: "found vulnerability in image",
+			args: args{
+				container: output.ContainerDetails{
+					Image: "test.azurecr.io/nginx:latest@sha256:3f13b4376446cf92b0cb9a5c46ba75d57",
+				},
+			},
+			fields: fields{
+				scanner: mockScanner{
+					queryError: nil,
+					validImage: true,
+					queryResponse: resourcegraph.QueryResponse{
+						Data: []output.ACRResponse{{
+							Properties: output.ACRVulnerabilityConfig{
+								ID: "test",
+								AdditionalData: output.ACRAdditionalData{
+									Cve: []output.ACRCve{
+										{
+											Link:  "http://link",
+											Title: "CVE-6767",
+										},
+									},
+								},
+							},
+						}},
+					},
+				},
+			},
+			wantVulnerabilities: []output.Vulnerability{
+				{
+					VulnerabilityID: "CVE-6767",
+					PrimaryURL:      "http://link",
+					CVSS: output.VendorCVSS{
+						"nvd": output.CVSS{},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			a := &ACR{
+				scanner: tt.fields.scanner,
+			}
+			if gotVulnerabilities := a.getVulnerabilities(tt.args.container, tt.args.options); !reflect.DeepEqual(gotVulnerabilities, tt.wantVulnerabilities) {
+				t.Errorf("ACR.getVulnerabilities() = %#v, want %v", gotVulnerabilities, tt.wantVulnerabilities)
+			}
+		})
+	}
+}
diff --git a/pkg/vulnerability/ecr_test.go b/pkg/vulnerability/ecr_test.go
new file mode 100644
index 000000000..4341aa7a2
--- /dev/null
+++ b/pkg/vulnerability/ecr_test.go
@@ -0,0 +1,448 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"context"
+	"fmt"
+	"reflect"
+	"testing"
+	"time"
+
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+	"github.com/aws/aws-sdk-go/aws/request"
+	"github.com/aws/aws-sdk-go/service/ecr"
+)
+
+type mockECRScanner struct {
+	client                          *ecr.ECR
+	scanfindings                    *ecr.DescribeImageScanFindingsOutput
+	scanfindingError                error
+	waitUntilImageScanCompleteError error
+	startImageScanOutput            *ecr.StartImageScanOutput
+	startImageScanError             error
+}
+
+func (m mockECRScanner) newClient() *ecr.ECR {
+	return m.client
+}
+
+func (m mockECRScanner) describeImageScanFindingsWithContext(ctx context.Context, client *ecr.ECR, input *ecr.DescribeImageScanFindingsInput, opts ...request.Option) (*ecr.DescribeImageScanFindingsOutput, error) {
+	return m.scanfindings, m.scanfindingError
+}
+
+func (m mockECRScanner) waitUntilImageScanComplete(client *ecr.ECR, input *ecr.DescribeImageScanFindingsInput) error {
+	return m.waitUntilImageScanCompleteError
+}
+
+func (m mockECRScanner) startImageScanWithContext(ctx context.Context, client *ecr.ECR, input *ecr.StartImageScanInput, opts ...request.Option) (*ecr.StartImageScanOutput, error) {
+	return m.startImageScanOutput, m.startImageScanError
+}
+
+func TestGetImageScanResult(t *testing.T) {
+	complete := "COMPLETE"
+	fail := "FAILED"
+	unknown := "UNKNOWN"
+	time := time.Now()
+	type fields struct {
+		scanner ecrScanner
+	}
+	type args struct {
+		ctx          context.Context
+		client       *ecr.ECR
+		image        string
+		imageDetails ImageDetails
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    *ecr.DescribeImageScanFindingsOutput
+		wantErr error
+	}{
+		{
+			name: "error finding scan vulnerability",
+			fields: fields{
+				scanner: mockECRScanner{
+					scanfindingError: fmt.Errorf("error finding vulnerability"),
+				},
+			},
+			args: args{
+				ctx:    context.Background(),
+				client: &ecr.ECR{},
+				image:  "24557.dkr.ecr.us-east-2.amazonaws.com/test:test",
+				imageDetails: ImageDetails{
+					Tag:        "test",
+					Repository: "test",
+					Registry:   "24557.dkr.ecr.us-east-2.amazonaws.com",
+				},
+			},
+			wantErr: fmt.Errorf("error finding vulnerability"),
+			want:    nil,
+		},
+		{
+			name: "found scan finding with status completed",
+			fields: fields{
+				scanner: mockECRScanner{
+					scanfindings: &ecr.DescribeImageScanFindingsOutput{
+						ImageScanStatus: &ecr.ImageScanStatus{
+							Status: &complete,
+						},
+						ImageScanFindings: &ecr.ImageScanFindings{
+							ImageScanCompletedAt: &time,
+						},
+					},
+				},
+			},
+			args: args{
+				ctx:    context.Background(),
+				client: &ecr.ECR{},
+				image:  "24557.dkr.ecr.us-east-2.amazonaws.com/test:test",
+				imageDetails: ImageDetails{
+					Tag:        "test",
+					Repository: "test",
+					Registry:   "24557.dkr.ecr.us-east-2.amazonaws.com",
+				},
+			},
+			wantErr: nil,
+			want: &ecr.DescribeImageScanFindingsOutput{
+				ImageScanStatus: &ecr.ImageScanStatus{
+					Status: &complete,
+				},
+				ImageScanFindings: &ecr.ImageScanFindings{
+					ImageScanCompletedAt: &time,
+				},
+			},
+		},
+		{
+			name: "found scan finding with status fail",
+			fields: fields{
+				scanner: mockECRScanner{
+					scanfindings: &ecr.DescribeImageScanFindingsOutput{
+						ImageScanStatus: &ecr.ImageScanStatus{
+							Status: &fail,
+						},
+						ImageScanFindings: &ecr.ImageScanFindings{
+							ImageScanCompletedAt: &time,
+						},
+					},
+				},
+			},
+			args: args{
+				ctx:    context.Background(),
+				client: &ecr.ECR{},
+				image:  "24557.dkr.ecr.us-east-2.amazonaws.com/test:test",
+				imageDetails: ImageDetails{
+					Tag:        "test",
+					Repository: "test",
+					Registry:   "24557.dkr.ecr.us-east-2.amazonaws.com",
+				},
+			},
+			wantErr: nil,
+			want: &ecr.DescribeImageScanFindingsOutput{
+				ImageScanStatus: &ecr.ImageScanStatus{
+					Status: &fail,
+				},
+				ImageScanFindings: &ecr.ImageScanFindings{
+					ImageScanCompletedAt: &time,
+				},
+			},
+		},
+		{
+			name: "found scan finding with status unknown",
+			fields: fields{
+				scanner: mockECRScanner{
+					scanfindings: &ecr.DescribeImageScanFindingsOutput{
+						ImageScanStatus: &ecr.ImageScanStatus{
+							Status: &unknown,
+						},
+						ImageScanFindings: &ecr.ImageScanFindings{
+							ImageScanCompletedAt: &time,
+						},
+					},
+				},
+			},
+			args: args{
+				ctx:    context.Background(),
+				client: &ecr.ECR{},
+				image:  "24557.dkr.ecr.us-east-2.amazonaws.com/test:test",
+				imageDetails: ImageDetails{
+					Tag:        "test",
+					Repository: "test",
+					Registry:   "24557.dkr.ecr.us-east-2.amazonaws.com",
+				},
+			},
+			wantErr: nil,
+			want: &ecr.DescribeImageScanFindingsOutput{
+				ImageScanStatus: &ecr.ImageScanStatus{
+					Status: &unknown,
+				},
+				ImageScanFindings: &ecr.ImageScanFindings{
+					ImageScanCompletedAt: &time,
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &ECR{
+				scanner: tt.fields.scanner,
+			}
+			got, err := e.GetImageScanResult(tt.args.ctx, tt.args.client, tt.args.image, tt.args.imageDetails)
+			if !reflect.DeepEqual(err, tt.wantErr) {
+				t.Errorf("ECR.GetImageScanResult() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ECR.GetImageScanResult() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestStartImageScan(t *testing.T) {
+	type fields struct {
+		scanner ecrScanner
+	}
+	type args struct {
+		ctx          context.Context
+		client       *ecr.ECR
+		image        string
+		imageDetails ImageDetails
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		wantErr error
+	}{
+		{
+			name: "error start image scan",
+			fields: fields{
+				scanner: mockECRScanner{
+					startImageScanError: fmt.Errorf("error starting image scan"),
+				},
+			},
+			args: args{
+				ctx:    context.Background(),
+				client: &ecr.ECR{},
+				image:  "24557.dkr.ecr.us-east-2.amazonaws.com/test:test",
+				imageDetails: ImageDetails{
+					Tag:        "test",
+					Repository: "test",
+					Registry:   "24557.dkr.ecr.us-east-2.amazonaws.com",
+				},
+			},
+			wantErr: fmt.Errorf("error starting image scan"),
+		},
+		{
+			name: "error while image scan to complete",
+			fields: fields{
+				scanner: mockECRScanner{
+					waitUntilImageScanCompleteError: fmt.Errorf("error image scan waiting"),
+				},
+			},
+			args: args{
+				ctx:    context.Background(),
+				client: &ecr.ECR{},
+				image:  "24557.dkr.ecr.us-east-2.amazonaws.com/test:test",
+				imageDetails: ImageDetails{
+					Tag:        "test",
+					Repository: "test",
+					Registry:   "24557.dkr.ecr.us-east-2.amazonaws.com",
+				},
+			},
+			wantErr: fmt.Errorf("error image scan waiting"),
+		},
+		{
+			name: "image scan started and complted successfully",
+			fields: fields{
+				scanner: mockECRScanner{},
+			},
+			args: args{
+				ctx:    context.Background(),
+				client: &ecr.ECR{},
+				image:  "24557.dkr.ecr.us-east-2.amazonaws.com/test:test",
+				imageDetails: ImageDetails{
+					Tag:        "test",
+					Repository: "test",
+					Registry:   "24557.dkr.ecr.us-east-2.amazonaws.com",
+				},
+			},
+			wantErr: nil,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &ECR{
+				scanner: tt.fields.scanner,
+			}
+			err := e.StartImageScan(tt.args.ctx, tt.args.client, tt.args.image, tt.args.imageDetails)
+			if !reflect.DeepEqual(err, tt.wantErr) {
+				t.Errorf("ECR.StartImageScan() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestECRScanImage(t *testing.T) {
+	complete := "COMPLETE"
+	time := time.Now()
+	type fields struct {
+		scanner ecrScanner
+	}
+	type args struct {
+		ctx   context.Context
+		image string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    *ecr.DescribeImageScanFindingsOutput
+		wantErr bool
+	}{
+		{
+			name: "inavlid image reference",
+			fields: fields{
+				scanner: mockECRScanner{},
+			},
+			args: args{
+				ctx:   context.Background(),
+				image: "test",
+			},
+			want:    nil,
+			wantErr: true,
+		},
+		{
+			name: "valid image reference",
+			fields: fields{
+				scanner: mockECRScanner{
+					scanfindings: &ecr.DescribeImageScanFindingsOutput{
+						ImageScanStatus: &ecr.ImageScanStatus{
+							Status: &complete,
+						},
+						ImageScanFindings: &ecr.ImageScanFindings{
+							ImageScanCompletedAt: &time,
+						},
+					},
+				},
+			},
+			args: args{
+				ctx:   context.Background(),
+				image: "24557.dkr.ecr.us-east-2.amazonaws.com/test",
+			},
+			want: &ecr.DescribeImageScanFindingsOutput{
+				ImageScanStatus: &ecr.ImageScanStatus{
+					Status: &complete,
+				},
+				ImageScanFindings: &ecr.ImageScanFindings{
+					ImageScanCompletedAt: &time,
+				},
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &ECR{
+				scanner: tt.fields.scanner,
+			}
+			got, err := e.ScanImage(tt.args.ctx, tt.args.image)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("ECR.ScanImage() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ECR.ScanImage() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestECRGetVulnerabilities(t *testing.T) {
+	complete := "COMPLETE"
+	severityLow := "Low"
+	time := time.Now()
+	type fields struct {
+		scanner ecrScanner
+	}
+	type args struct {
+		container output.ContainerDetails
+		options   map[string]interface{}
+	}
+	tests := []struct {
+		name                string
+		fields              fields
+		args                args
+		wantVulnerabilities []output.Vulnerability
+	}{
+		{
+			name: "invalid image reference",
+			fields: fields{
+				scanner: mockECRScanner{},
+			},
+			args: args{
+				container: output.ContainerDetails{
+					Image: "test",
+				},
+			},
+			wantVulnerabilities: nil,
+		},
+		{
+			name: "found image vulnerabilities",
+			fields: fields{
+				scanner: mockECRScanner{
+					scanfindings: &ecr.DescribeImageScanFindingsOutput{
+						ImageScanStatus: &ecr.ImageScanStatus{
+							Status: &complete,
+						},
+						ImageScanFindings: &ecr.ImageScanFindings{
+							ImageScanCompletedAt: &time,
+							Findings: []*ecr.ImageScanFinding{
+								{
+									Severity: &severityLow,
+								},
+							},
+						},
+					},
+				},
+			},
+			args: args{
+				container: output.ContainerDetails{
+					Image: "24557.dkr.ecr.us-east-2.amazonaws.com/test",
+				},
+			},
+			wantVulnerabilities: []output.Vulnerability{
+				{
+					PrimaryURL: "https://cve.mitre.org/cgi-bin/cvename.cgi?name=",
+					Severity:   "LOW",
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			e := &ECR{
+				scanner: tt.fields.scanner,
+			}
+			if gotVulnerabilities := e.getVulnerabilities(tt.args.container, tt.args.options); !reflect.DeepEqual(gotVulnerabilities, tt.wantVulnerabilities) {
+				t.Errorf("ECR.getVulnerabilities() = %v, want %v", gotVulnerabilities, tt.wantVulnerabilities)
+			}
+		})
+	}
+}
diff --git a/pkg/vulnerability/gcr_test.go b/pkg/vulnerability/gcr_test.go
new file mode 100644
index 000000000..d4dfe649b
--- /dev/null
+++ b/pkg/vulnerability/gcr_test.go
@@ -0,0 +1,222 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"context"
+	"fmt"
+	"reflect"
+	"testing"
+
+	containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+	grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
+)
+
+type mockGCRScanner struct {
+	client         *containeranalysis.Client
+	newClientErr   error
+	closeErr       error
+	occurrences    []*grafeaspb.Occurrence
+	occurrencesErr error
+}
+
+func (m mockGCRScanner) newClient(ctx context.Context) (*containeranalysis.Client, error) {
+	return m.client, m.newClientErr
+}
+
+func (m mockGCRScanner) close(client *containeranalysis.Client) error {
+	return m.closeErr
+}
+
+func (m mockGCRScanner) listOccurrences(ctx context.Context, client *containeranalysis.Client, req *grafeaspb.ListOccurrencesRequest) ([]*grafeaspb.Occurrence, error) {
+	return m.occurrences, m.occurrencesErr
+}
+
+func TestGetProjectIDFromImageName(t *testing.T) {
+	type args struct {
+		image string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    string
+		wantErr error
+	}{
+		{
+			name: "invalid image reference",
+			args: args{
+				image: "test",
+			},
+			want:    "",
+			wantErr: fmt.Errorf(invalidImageReferenceMsg, "test"),
+		},
+		{
+			name: "valid image reference",
+			args: args{
+				image: "gcr.io/test/test-image",
+			},
+			want:    "test",
+			wantErr: nil,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := getProjectIDFromImageName(tt.args.image)
+			if !reflect.DeepEqual(err, tt.wantErr) {
+				t.Errorf("getProjectIDFromImageName() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if got != tt.want {
+				t.Errorf("getProjectIDFromImageName() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGCRScanImage(t *testing.T) {
+	type fields struct {
+		scanner gcrScanner
+	}
+	type args struct {
+		image string
+	}
+	tests := []struct {
+		name       string
+		fields     fields
+		args       args
+		wantResult []*grafeaspb.Occurrence
+		wantErr    error
+	}{
+		{
+			name: "client create error",
+			args: args{
+				image: "gcr.io/test/test-image@sha256:3f13b4376446cf",
+			},
+			fields: fields{
+				scanner: mockGCRScanner{
+					newClientErr: fmt.Errorf("error creating new client"),
+				},
+			},
+			wantResult: nil,
+			wantErr:    fmt.Errorf("error creating new client"),
+		},
+		{
+			name: "found vulnerability",
+			args: args{
+				image: "gcr.io/test/test-image@sha256:3f13b4376446cf",
+			},
+			fields: fields{
+				scanner: mockGCRScanner{
+					occurrences: []*grafeaspb.Occurrence{},
+				},
+			},
+			wantResult: []*grafeaspb.Occurrence{},
+			wantErr:    nil,
+		},
+		{
+			name: "invalid image reference",
+			args: args{
+				image: "test-image@sha256:3f13b4376446cf",
+			},
+			fields: fields{
+				scanner: mockGCRScanner{},
+			},
+			wantResult: nil,
+			wantErr:    fmt.Errorf("invalid image reference test-image@sha256:3f13b4376446cf "),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			g := &GCR{
+				scanner: tt.fields.scanner,
+			}
+			gotResult, err := g.ScanImage(tt.args.image)
+			if !reflect.DeepEqual(err, tt.wantErr) {
+				t.Errorf("GCR.ScanImage() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(gotResult, tt.wantResult) {
+				t.Errorf("GCR.ScanImage() = %v, want %v", gotResult, tt.wantResult)
+			}
+		})
+	}
+}
+
+func TestGCRGetVulnerabilities(t *testing.T) {
+	type fields struct {
+		scanner gcrScanner
+	}
+	type args struct {
+		container output.ContainerDetails
+		options   map[string]interface{}
+	}
+	tests := []struct {
+		name                string
+		fields              fields
+		args                args
+		wantVulnerabilities []output.Vulnerability
+	}{
+		{
+			name: "invalid image reference",
+			args: args{
+				container: output.ContainerDetails{
+					Image: "test-image@sha256:3f13b4376446cf",
+				},
+			},
+			fields: fields{
+				scanner: mockGCRScanner{},
+			},
+			wantVulnerabilities: nil,
+		},
+		{
+			name: "vulnerabilities found",
+			args: args{
+				container: output.ContainerDetails{
+					Image: "gcr.io/test/test-image@sha256:3f13b4376446cf",
+				},
+			},
+			fields: fields{
+				scanner: mockGCRScanner{
+					occurrences: []*grafeaspb.Occurrence{
+						{NoteName: "test/cve-1342"},
+					},
+				},
+			},
+			wantVulnerabilities: []output.Vulnerability{
+				{
+					VulnerabilityID: "cve-1342",
+					Severity:        "SEVERITY_UNSPECIFIED",
+					PrimaryURL:      "https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-1342",
+					CVSS: output.VendorCVSS{
+						"nvd": output.CVSS{},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			g := &GCR{
+				scanner: tt.fields.scanner,
+			}
+			if gotVulnerabilities := g.getVulnerabilities(tt.args.container, tt.args.options); !reflect.DeepEqual(gotVulnerabilities, tt.wantVulnerabilities) {
+				t.Errorf("GCR.getVulnerabilities() = %#v, want %v", gotVulnerabilities, tt.wantVulnerabilities)
+			}
+		})
+	}
+}
diff --git a/pkg/vulnerability/types_test.go b/pkg/vulnerability/types_test.go
new file mode 100644
index 000000000..390f7e645
--- /dev/null
+++ b/pkg/vulnerability/types_test.go
@@ -0,0 +1,221 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestGetImageDetails(t *testing.T) {
+	type args struct {
+		image        string
+		imageDetails ImageDetails
+	}
+	tests := []struct {
+		name string
+		args args
+		want ImageDetails
+	}{
+		{
+			name: "gcr image without tag and digest",
+			args: args{
+				image:        "gcr.io/terrascan-test",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "gcr.io",
+				Repository: "terrascan-test",
+			},
+		},
+		{
+			name: "gcr image with tag and digest",
+			args: args{
+				image:        "gcr.io/terrascan-test:test@sha256:3f13b4376446cf92b0cb9a5c4",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "gcr.io",
+				Repository: "terrascan-test",
+				Tag:        "test",
+				Digest:     "sha256:3f13b4376446cf92b0cb9a5c4",
+			},
+		},
+		{
+			name: "gcr image with tag",
+			args: args{
+				image:        "gcr.io/terrascan-test:test",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "gcr.io",
+				Repository: "terrascan-test",
+				Tag:        "test",
+			},
+		},
+		{
+			name: "gcr image with Digest",
+			args: args{
+				image:        "gcr.io/terrascan-test@sha256:3f13b4376446cf92b0cb9a5c4",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "gcr.io",
+				Repository: "terrascan-test",
+				Digest:     "sha256:3f13b4376446cf92b0cb9a5c4",
+			},
+		},
+		{
+			name: "ecr image without tag and digest",
+			args: args{
+				image:        "245578968.dkr.ecr.us-east-2.amazonaws.com/terrascan-test",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "245578968.dkr.ecr.us-east-2.amazonaws.com",
+				Repository: "terrascan-test",
+			},
+		},
+		{
+			name: "ecr image with tag and digest",
+			args: args{
+				image:        "245578968.dkr.ecr.us-east-2.amazonaws.com/terrascan-test:test@sha256:3f13b4376446cf92b0cb9a5c4",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "245578968.dkr.ecr.us-east-2.amazonaws.com",
+				Repository: "terrascan-test",
+				Tag:        "test",
+				Digest:     "sha256:3f13b4376446cf92b0cb9a5c4",
+			},
+		},
+		{
+			name: "ecr image with tag",
+			args: args{
+				image:        "245578968.dkr.ecr.us-east-2.amazonaws.com/terrascan-test:test",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "245578968.dkr.ecr.us-east-2.amazonaws.com",
+				Repository: "terrascan-test",
+				Tag:        "test",
+			},
+		},
+		{
+			name: "ecr image with  digest",
+			args: args{
+				image:        "245578968.dkr.ecr.us-east-2.amazonaws.com/terrascan-test@sha256:3f13b4376446cf92b0cb9a5c4",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "245578968.dkr.ecr.us-east-2.amazonaws.com",
+				Repository: "terrascan-test",
+				Digest:     "sha256:3f13b4376446cf92b0cb9a5c4",
+			},
+		},
+		{
+			name: "acr image without tag and digest",
+			args: args{
+				image:        "test.azurecr.io/terrascan-test",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "test.azurecr.io",
+				Repository: "terrascan-test",
+			},
+		},
+		{
+			name: "acr image with tag and digest",
+			args: args{
+				image:        "test.azurecr.io/terrascan-test:test@sha256:3f13b4376446cf92b0cb9a5c4",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "test.azurecr.io",
+				Repository: "terrascan-test",
+				Tag:        "test",
+				Digest:     "sha256:3f13b4376446cf92b0cb9a5c4",
+			},
+		},
+		{
+			name: "acr image with tag",
+			args: args{
+				image:        "test.azurecr.io/terrascan-test:test",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "test.azurecr.io",
+				Repository: "terrascan-test",
+				Tag:        "test",
+			},
+		},
+		{
+			name: "acr image with Digest",
+			args: args{
+				image:        "test.azurecr.io/terrascan-test@sha256:3f13b4376446cf92b0cb9a5c4",
+				imageDetails: ImageDetails{},
+			},
+			want: ImageDetails{
+				Registry:   "test.azurecr.io",
+				Repository: "terrascan-test",
+				Digest:     "sha256:3f13b4376446cf92b0cb9a5c4",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := GetImageDetails(tt.args.image, tt.args.imageDetails); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetImageDetails() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetDomain(t *testing.T) {
+	type args struct {
+		image string
+	}
+	tests := []struct {
+		name string
+		args args
+		want string
+	}{
+		{name: "get gcr image domain",
+			args: args{image: "gcr.io/terrascan-test"},
+			want: "gcr.io",
+		},
+		{name: "get acr image domain",
+			args: args{image: "test.azurecr.io/terrascan-test"},
+			want: "test.azurecr.io",
+		},
+		{name: "get ecr image domain",
+			args: args{image: "245578968.dkr.ecr.us-east-2.amazonaws.com/terrascan-test"},
+			want: "245578968.dkr.ecr.us-east-2.amazonaws.com",
+		},
+		{name: "inavlid image domain reference",
+			args: args{image: ""},
+			want: "",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := GetDomain(tt.args.image); got != tt.want {
+				t.Errorf("GetDomain() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/pkg/vulnerability/vulnerability_test.go b/pkg/vulnerability/vulnerability_test.go
new file mode 100644
index 000000000..095ec7967
--- /dev/null
+++ b/pkg/vulnerability/vulnerability_test.go
@@ -0,0 +1,264 @@
+/*
+    Copyright (C) 2020 Accurics, Inc.
+
+	Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+		http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+package vulnerability
+
+import (
+	"encoding/xml"
+	"reflect"
+	"strings"
+	"testing"
+
+	"github.com/accurics/terrascan/pkg/iac-providers/output"
+	"github.com/accurics/terrascan/pkg/results"
+)
+
+var resourceConfigs = output.AllResourceConfigs{
+	"test": []output.ResourceConfig{
+		{
+			ContainerImages: []output.ContainerDetails{
+				{
+					Name:  "test",
+					Image: "test",
+					Vulnerabilities: []output.Vulnerability{
+						{Severity: "low",
+							CVSS: output.VendorCVSS{
+								"nvd": output.CVSS{
+									V2Vector: "test",
+									V3Vector: "test",
+									V2Score:  8,
+									V3Score:  6,
+								},
+							}},
+					},
+				},
+			},
+			InitContainerImages: []output.ContainerDetails{
+				{
+					Name:  "inittest",
+					Image: "test",
+					Vulnerabilities: []output.Vulnerability{
+						{Severity: "high",
+							CVSS: output.VendorCVSS{
+								"nvd": output.CVSS{
+									V2Vector: "test",
+									V3Vector: "test",
+									V2Score:  8,
+									V3Score:  6,
+								},
+							}},
+					},
+				},
+			},
+		},
+	},
+}
+
+func TestPrepareVulnerabilityObject(t *testing.T) {
+	options := make(map[string]interface{})
+	type args struct {
+		container output.ContainerDetails
+		resource  output.ResourceConfig
+	}
+	tests := []struct {
+		name string
+		args args
+		want []*results.Vulnerability
+	}{
+		{name: "output with 1 result",
+			args: args{
+				container: output.ContainerDetails{
+					Name:  "test",
+					Image: "test",
+					Vulnerabilities: []output.Vulnerability{
+						{Severity: "low",
+							CVSS: output.VendorCVSS{
+								"nvd": output.CVSS{
+									V2Vector: "test",
+									V3Vector: "test",
+									V2Score:  8,
+									V3Score:  6,
+								},
+							}},
+					},
+				},
+				resource: output.ResourceConfig{
+					Line:   2,
+					Type:   "test",
+					Source: "test",
+					Name:   "test",
+				},
+			},
+			want: []*results.Vulnerability{
+				{
+					Image:        "test",
+					Container:    "test",
+					Severity:     strings.ToUpper("low"),
+					File:         "test",
+					LineNumber:   2,
+					ResourceType: "test",
+					ResourceName: "test",
+					CVSSScore: results.CVSS{
+						V2Vector: "test",
+						V3Vector: "test",
+						V2Score:  8,
+						V3Score:  6,
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := prepareVulnerabilityObject(tt.args.container, tt.args.resource, options); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("prepareVulnerabilityObject() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetVulnerabilitiesByRepository(t *testing.T) {
+	options := make(map[string]interface{})
+	type args struct {
+		container output.ContainerDetails
+	}
+	tests := []struct {
+		name string
+		args args
+		want []output.Vulnerability
+	}{
+		{
+			name: "no registered registries",
+			args: args{
+				container: output.ContainerDetails{
+					Image: "test",
+				},
+			},
+			want: []output.Vulnerability{},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := getVulnerabilitiesByRepository(tt.args.container, options); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("getVulnerabilitiesByRepository() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestVulEngine_ReportVulnerability(t *testing.T) {
+	count := 2
+	type fields struct {
+		results EngineOutput
+	}
+	type args struct {
+		engineInput EngineInput
+		options     map[string]interface{}
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   EngineOutput
+	}{
+		{
+			name: "get vulnerability",
+			args: args{
+				engineInput: EngineInput{
+					InputData: &resourceConfigs,
+				},
+			},
+			fields: fields{},
+			want: EngineOutput{
+				XMLName: xml.Name{Space: "", Local: ""},
+				ViolationStore: &results.ViolationStore{
+					Summary: results.ScanSummary{
+						Vulnerabilities: &count,
+					},
+					Vulnerabilities: []*results.Vulnerability{
+						{
+							Image:     "test",
+							Container: "test",
+							Severity:  strings.ToUpper("low"),
+							CVSSScore: results.CVSS{
+								V2Vector: "test",
+								V3Vector: "test",
+								V2Score:  8,
+								V3Score:  6,
+							},
+						},
+						{
+							Image:     "test",
+							Container: "inittest",
+							Severity:  strings.ToUpper("high"),
+							CVSSScore: results.CVSS{
+								V2Vector: "test",
+								V3Vector: "test",
+								V2Score:  8,
+								V3Score:  6,
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &VulEngine{
+				results: tt.fields.results,
+			}
+			if got := v.ReportVulnerability(tt.args.engineInput, tt.args.options); !reflect.DeepEqual(got.ViolationStore.Vulnerabilities, tt.want.ViolationStore.Vulnerabilities) {
+				t.Errorf("VulEngine.ReportVulnerability() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestVulEngineFetchVulnerabilities(t *testing.T) {
+	type fields struct {
+		results EngineOutput
+	}
+	type args struct {
+		resourceConfigs output.AllResourceConfigs
+		options         map[string]interface{}
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   output.AllResourceConfigs
+	}{
+		{
+			name:   "find vulnerabilities",
+			fields: fields{},
+			args: args{
+				resourceConfigs: resourceConfigs,
+			},
+			want: resourceConfigs,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			v := &VulEngine{
+				results: tt.fields.results,
+			}
+			if got := v.FetchVulnerabilities(tt.args.resourceConfigs, tt.args.options); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("VulEngine.FindVulnerabilities() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/pkg/writer/human_readable_test.go b/pkg/writer/human_readable_test.go
index 8b181670a..9cad0d1ab 100644
--- a/pkg/writer/human_readable_test.go
+++ b/pkg/writer/human_readable_test.go
@@ -36,6 +36,31 @@ var (
 			Summary: summaryWithNoViolations,
 		},
 	}
+	vulnerabilitiesInputHumanReadable = policy.EngineOutput{
+		ViolationStore: &results.ViolationStore{
+			Vulnerabilities: []*results.Vulnerability{
+				{
+					Image:           "test",
+					Container:       "test",
+					VulnerabilityID: "CVE-2019-18276",
+					PrimaryURL:      "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18276",
+					Description:     "GNU Bash. Bash is the GNU Project's shell",
+					Severity:        "HIGH",
+				},
+			},
+			Summary: results.ScanSummary{
+				ResourcePath:     "test",
+				IacType:          "terraform",
+				Timestamp:        "2020-12-12 11:21:29.902796 +0000 UTC",
+				TotalPolicies:    566,
+				LowCount:         0,
+				MediumCount:      0,
+				HighCount:        1,
+				ViolatedPolicies: 1,
+				Vulnerabilities:  &summaryWithNoViolations.ViolatedPolicies,
+			},
+		},
+	}
 )
 
 const (
@@ -113,6 +138,33 @@ Scan Summary -
 	Low                 :	0
 	Medium              :	0
 	High                :	1`
+
+	vulnerabilityScanOutputHumanReadable = `Vulnerabilities Details - 
+    
+	Description         :	GNU Bash. Bash is the GNU Project's shell
+	Vulnerability ID    :	CVE-2019-18276
+	Resource Name       :	""
+	Resource Type       :	
+	Image               :	test
+	Package             :	
+	Line                :	0
+	Primary URL         :	http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18276
+	Primary URL         :	HIGH
+	
+	-----------------------------------------------------------------------
+	
+
+Scan Summary -
+
+	File/Folder         :	test
+	IaC Type            :	terraform
+	Scanned At          :	2020-12-12 11:21:29.902796 +0000 UTC
+	Policies Validated  :	566
+	Violated Policies   :	1
+	Low                 :	0
+	Medium              :	0
+	High                :	1
+	Vulnerabilities     :	1`
 )
 
 func TestHumanReadbleWriter(t *testing.T) {
@@ -143,6 +195,11 @@ func TestHumanReadbleWriter(t *testing.T) {
 			input:          outputWithPassedRules,
 			expectedOutput: expectedOutput3,
 		},
+		{
+			name:           "Human Readable Writer: With Vulnerabilities",
+			input:          vulnerabilitiesInputHumanReadable,
+			expectedOutput: vulnerabilityScanOutputHumanReadable,
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/pkg/writer/json_test.go b/pkg/writer/json_test.go
index 419060baa..c64763485 100644
--- a/pkg/writer/json_test.go
+++ b/pkg/writer/json_test.go
@@ -66,6 +66,36 @@ const (
     }
   }
 }`
+
+	vulnerabilityScanOutputJSON = `{
+  "results": {
+    "violations": null,
+    "skipped_violations": null,
+    "vulnerabilities": [
+      {
+        "image": "test",
+        "container": "test",
+        "severity": "HIGH",
+        "cvss_score": {},
+        "description": "GNU Bash. Bash is the GNU Project's shell",
+        "vulnerability_id": "CVE-2019-18276",
+        "primary_url": "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18276",
+        "resource_name": "",
+        "resource_type": ""
+      }
+    ],
+    "scan_summary": {
+      "file/folder": "",
+      "iac_type": "",
+      "scanned_at": "",
+      "policies_validated": 0,
+      "violated_policies": 0,
+      "low": 0,
+      "medium": 0,
+      "high": 0
+    }
+  }
+}`
 )
 
 func TestJSONWriter(t *testing.T) {
@@ -85,6 +115,11 @@ func TestJSONWriter(t *testing.T) {
 			input:          violationsInput,
 			expectedOutput: scanTestOutputJSON,
 		},
+		{
+			name:           "JSON Writer: Vulnerabilities",
+			input:          vulnerabilitiesInput,
+			expectedOutput: vulnerabilityScanOutputJSON,
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/pkg/writer/yaml_test.go b/pkg/writer/yaml_test.go
index 73eacea7d..a43e289c9 100644
--- a/pkg/writer/yaml_test.go
+++ b/pkg/writer/yaml_test.go
@@ -28,6 +28,21 @@ var (
 		},
 	}
 
+	vulnerabilitiesInput = policy.EngineOutput{
+		ViolationStore: &results.ViolationStore{
+			Vulnerabilities: []*results.Vulnerability{
+				{
+					Image:           "test",
+					Container:       "test",
+					VulnerabilityID: "CVE-2019-18276",
+					PrimaryURL:      "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18276",
+					Description:     "GNU Bash. Bash is the GNU Project's shell",
+					Severity:        "HIGH",
+				},
+			},
+		},
+	}
+
 	violationsInput = policy.EngineOutput{
 		ViolationStore: &results.ViolationStore{
 			Violations: []*results.Violation{
@@ -118,6 +133,28 @@ const (
         low: 0
         medium: 0
         high: 1`
+
+	vulnerabilityScanOutput = `results:
+    violations: []
+    skipped_violations: []
+    vulnerabilities:
+        - image: test
+          container: test
+          severity: HIGH
+          description: GNU Bash. Bash is the GNU Project's shell
+          vulnerability_id: CVE-2019-18276
+          primary_url: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18276
+          resource_name: ""
+          resource_type: ""
+    scan_summary:
+        file/folder: ""
+        iac_type: ""
+        scanned_at: ""
+        policies_validated: 0
+        violated_policies: 0
+        low: 0
+        medium: 0
+        high: 0`
 )
 
 func TestYAMLWriter(t *testing.T) {
@@ -137,6 +174,11 @@ func TestYAMLWriter(t *testing.T) {
 			input:          violationsInput,
 			expectedOutput: scanTestOutputYAML,
 		},
+		{
+			name:           "YAML Writer: Vulnerabilities",
+			input:          vulnerabilitiesInput,
+			expectedOutput: vulnerabilityScanOutput,
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/test/e2e/help/golden/help_scan.txt b/test/e2e/help/golden/help_scan.txt
index 7aa979780..d30d315fc 100644
--- a/test/e2e/help/golden/help_scan.txt
+++ b/test/e2e/help/golden/help_scan.txt
@@ -8,6 +8,7 @@ Usage:
 Flags:
       --categories strings        list of categories of violations to be reported by terrascan (example: --categories="category1,category2")
       --config-only               will output resource config (should only be used for debugging purposes)
+      --find-vuln                 fetches vulnerabilities identified in Docker images
   -h, --help                      help for scan
   -d, --iac-dir string            path to a directory containing one or more IaC files (default ".")
   -f, --iac-file string           path to a single IaC file