Skip to content

Commit

Permalink
Fix trivy parsing for terraform (#775)
Browse files Browse the repository at this point in the history
Otherwise we were getting results on line 130 for a 24 line file. Added
regression test as well.

Also adds comment style for terraform filetype.
  • Loading branch information
TylerJang27 committed May 10, 2024
1 parent 6cfcfea commit ac24ac1
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 69 deletions.
4 changes: 4 additions & 0 deletions linters/plugin.yaml
Expand Up @@ -572,6 +572,10 @@ lint:
extensions:
- tf
- tf.json
comments:
- hash
- slashes-inline
- slashes-block

- name: textproto
extensions:
Expand Down
139 changes: 75 additions & 64 deletions linters/trivy/config_expected_issues.json
@@ -1,158 +1,169 @@
[
{
"file": "test_data/aws.tf",
"line": "1",
"message": "Instance does not require IMDS access to require a token",
"code": "AVD-AWS-0028",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "terraform",
"isSecurity": true,
"message": "Instance does not require IMDS access to require a token",
"file": "test_data/aws.tf"
"isSecurity": true
},
{
"file": "test_data/aws.tf",
"line": "1",
"message": "Root block device is not encrypted.",
"code": "AVD-AWS-0131",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "terraform",
"isSecurity": true,
"message": "Root block device is not encrypted.",
"file": "test_data/aws.tf"
"isSecurity": true
},
{
"code": "DS026",
"file": "test_data/basic.Dockerfile",
"message": "Specify at least 1 USER command in Dockerfile with non-root user as argument",
"code": "DS002",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "docker",
"isSecurity": true,
"message": "Add HEALTHCHECK instruction in your Dockerfile",
"file": "test_data/basic.Dockerfile"
"isSecurity": true
},
{
"code": "DS002",
"file": "test_data/basic.Dockerfile",
"message": "Add HEALTHCHECK instruction in your Dockerfile",
"code": "DS026",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "docker",
"isSecurity": true,
"message": "Specify at least 1 USER command in Dockerfile with non-root user as argument",
"file": "test_data/basic.Dockerfile"
"isSecurity": true
},
{
"code": "KSV116",
"file": "test_data/basic.yaml",
"message": "container \"sec-ctx-demo\" of pod \"security-context-demo\" in \"default\" namespace should specify a seccomp profile",
"code": "KSV104",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "pod security-context-demo in default namespace should set spec.securityContext.runAsGroup, spec.securityContext.supplementalGroups[*] and spec.securityContext.fsGroup to integer greater than 0",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"code": "KSV104",
"file": "test_data/basic.yaml",
"line": "14",
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should add 'ALL' to 'securityContext.capabilities.drop'",
"code": "KSV003",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "container sec-ctx-demo of pod security-context-demo in default namespace should specify a seccomp profile",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV106",
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'resources.limits.cpu'",
"code": "KSV011",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "container should drop all",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV020",
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'securityContext.runAsNonRoot' to true",
"code": "KSV012",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'securityContext.runAsUser' > 10000",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV003",
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should specify an image tag",
"code": "KSV013",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should add 'ALL' to 'securityContext.capabilities.drop'",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV013",
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'securityContext.readOnlyRootFilesystem' to true",
"code": "KSV014",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should specify an image tag",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV021",
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'resources.limits.memory'",
"code": "KSV018",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'securityContext.runAsGroup' > 10000",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV014",
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'securityContext.runAsUser' > 10000",
"code": "KSV020",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'securityContext.readOnlyRootFilesystem' to true",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV030",
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'securityContext.runAsGroup' > 10000",
"code": "KSV021",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Either Pod or Container should set 'securityContext.seccompProfile.type' to 'RuntimeDefault'",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV011",
"message": "Either Pod or Container should set 'securityContext.seccompProfile.type' to 'RuntimeDefault'",
"code": "KSV030",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'resources.limits.cpu'",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"file": "test_data/basic.yaml",
"line": "14",
"code": "KSV012",
"message": "container should drop all",
"code": "KSV106",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'securityContext.runAsNonRoot' to true",
"file": "test_data/basic.yaml"
"isSecurity": true
},
{
"line": "14",
"code": "KSV018",
"file": "test_data/main.tf",
"line": "17",
"message": "IAM policy document uses sensitive action 'logs:CreateLogGroup' on wildcarded resource '34c9c025-d988-4bcc-9d4a-4581749e7576:*'",
"code": "AVD-AWS-0057",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "yaml",
"isSecurity": true,
"message": "Container 'sec-ctx-demo' of Pod 'security-context-demo' should set 'resources.limits.memory'",
"file": "test_data/basic.yaml"
"targetType": "terraform",
"isSecurity": true
},
{
"file": "test_data/main.tf",
"line": "17",
"message": "Function does not have tracing enabled.",
"code": "AVD-AWS-0066",
"level": "LEVEL_HIGH",
"linter": "trivy",
"targetType": "terraform",
"isSecurity": true
}
]
1 change: 1 addition & 0 deletions linters/trivy/plugin.yaml
Expand Up @@ -30,6 +30,7 @@ lint:
suggest_if: files_present
description: A comprehensive and versatile security scanner
known_good_version: 0.44.1
# trivy supports --format template --template "@contrib/sarif.tpl", but it reports the wrong filepaths.
commands:
- name: fs-vuln
files: [lockfile]
Expand Down
34 changes: 34 additions & 0 deletions linters/trivy/test_data/main.tf
@@ -0,0 +1,34 @@
terraform {
required_version = ">= 1.4.6"
backend "local" {
path = "terraform.tfstate"
}
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.47.0"
}
}
}

# AWS Provider
provider "aws" {}

module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
version = "7.4.0"
function_name = "LambdaFunction"
handler = "lambda_handler.lambda_handler"
runtime = "python3.12"
local_existing_package = "lambda_package.zip"
create_package = false
create_current_version_allowed_triggers = false
attach_policy_json = false
timeout = 900
ignore_source_code_hash = true
maximum_retry_attempts = 0
# Because tc-db is private, this lambda function must run within the VPC
vpc_subnet_ids = ["subnet-1", "subnet-2", "subnet-3"]
vpc_security_group_ids = ["security-group-1", "security-group-2"]
attach_network_policy = true
}
9 changes: 9 additions & 0 deletions linters/trivy/test_data/trivy_v0.44.1_config.check.shot
Expand Up @@ -49,6 +49,15 @@ exports[`Testing linter trivy test config 1`] = `
],
"verb": "TRUNK_VERB_CHECK",
},
{
"command": "config",
"fileGroupName": "terraform",
"linter": "trivy",
"paths": [
"test_data/main.tf",
],
"verb": "TRUNK_VERB_CHECK",
},
],
"taskFailures": [],
"unformattedFiles": [],
Expand Down
9 changes: 9 additions & 0 deletions linters/trivy/test_data/trivy_v0.44.1_fs-secret.check.shot
Expand Up @@ -96,6 +96,15 @@ exports[`Testing linter trivy test fs-secret 1`] = `
],
"verb": "TRUNK_VERB_CHECK",
},
{
"command": "fs-secret",
"fileGroupName": "ALL",
"linter": "trivy",
"paths": [
"test_data/main.tf",
],
"verb": "TRUNK_VERB_CHECK",
},
{
"command": "fs-secret",
"fileGroupName": "ALL",
Expand Down
16 changes: 11 additions & 5 deletions linters/trivy/trivy_config_to_sarif.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

import json
import os
import sys


Expand Down Expand Up @@ -29,6 +30,7 @@ def to_result_sarif(path: str, vuln_id: str, description: str, line: int = 0):

def main(argv):
trivy_json = json.load(sys.stdin)
path = trivy_json["ArtifactName"]
results = []

for result in trivy_json.get("Results", []):
Expand All @@ -37,11 +39,15 @@ def main(argv):
for vuln in result["Misconfigurations"]:
vuln_id = vuln["ID"]
message = vuln["Message"]
line_num = vuln.get("CauseMetadata", {}).get("StartLine", 0)

results.append(
to_result_sarif(trivy_json["ArtifactName"], vuln_id, message, line_num)
)
location_info = vuln.get("CauseMetadata", {})
line_num = location_info.get("StartLine", 0)
for occurrence in location_info.get("Occurrences", []):
# Sometimes the original StartLine will reference a resource file
if occurrence.get("Filename") == os.path.basename(path):
line_num = occurrence["Location"]["StartLine"]
break

results.append(to_result_sarif(path, vuln_id, message, line_num))

sarif = {
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
Expand Down

0 comments on commit ac24ac1

Please sign in to comment.