diff --git a/.github/actions/linter_tests/action.yaml b/.github/actions/linter_tests/action.yaml index 0f2af97d3..40850c627 100644 --- a/.github/actions/linter_tests/action.yaml +++ b/.github/actions/linter_tests/action.yaml @@ -20,6 +20,9 @@ inputs: description: Additional args to append to the test invocation required: false default: linters -- + snyk-token: + description: Token to login for snyk test + required: true sourcery-token: description: Token to login for sourcery test required: true @@ -103,6 +106,7 @@ runs: PLUGINS_TEST_LINTER_VERSION: ${{ inputs.linter-version }} PLUGINS_TEST_CLI_VERSION: ${{ inputs.cli-version }} PLUGINS_TEST_CLI_PATH: ${{ env.CLI_PATH }} + SNYK_TOKEN: ${{ inputs.snyk-token }} SOURCERY_TOKEN: ${{ inputs.sourcery-token }} # Debug recurrent eslint circular JSON errors DEBUG: Driver:eslint:*,Driver:nixpkgs-fmt:*,Driver:trunk-toolbox:* diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 1bf379b15..97dac1ddc 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -67,6 +67,7 @@ jobs: with: linter-version: ${{ matrix.linter-version }} ref-type: main + snyk-token: ${{ secrets.TRUNK_SNYK_TOKEN }} sourcery-token: ${{ secrets.TRUNK_SOURCERY_TOKEN }} trunk-staging-token: ${{ secrets.TRUNK_DEBUGGER_TOKEN }} trunk-prod-token: ${{ secrets.TRUNK_ORG_PROD_TOKEN }} @@ -173,6 +174,7 @@ jobs: linter-version: ${{ matrix.linter-version }} append-args: linters -- --json --outputFile=${{ matrix.results-file }}-res.json ref-type: release + snyk-token: ${{ secrets.TRUNK_SNYK_TOKEN }} sourcery-token: ${{ secrets.TRUNK_SOURCERY_TOKEN }} trunk-staging-token: ${{ secrets.TRUNK_DEBUGGER_TOKEN }} trunk-prod-token: ${{ secrets.TRUNK_ORG_PROD_TOKEN }} @@ -198,6 +200,7 @@ jobs: TRUNK_API_TOKEN: ${{ secrets.TRUNK_API_TOKEN }} TRUNK_OPEN_PR_APP_ID: ${{ secrets.TRUNK_OPEN_PR_APP_ID }} TRUNK_OPEN_PR_APP_PRIVATE_KEY: ${{ secrets.TRUNK_OPEN_PR_APP_PRIVATE_KEY }} + TRUNK_SNYK_TOKEN: ${{ secrets.TRUNK_SNYK_TOKEN }} TRUNK_SOURCERY_TOKEN: ${{ secrets.TRUNK_SOURCERY_TOKEN }} TRUNK_DEBUGGER_TOKEN: ${{ secrets.TRUNK_DEBUGGER_TOKEN }} TRUNK_ORG_PROD_TOKEN: ${{ secrets.TRUNK_ORG_PROD_TOKEN }} @@ -254,6 +257,7 @@ jobs: uses: ./.github/workflows/upload_results.reusable.yaml secrets: TRUNKBOT_SLACK_BOT_TOKEN: ${{ secrets.TRUNKBOT_SLACK_BOT_TOKEN }} + TRUNK_SNYK_TOKEN: ${{ secrets.TRUNK_SNYK_TOKEN }} TRUNK_SOURCERY_TOKEN: ${{ secrets.TRUNK_SOURCERY_TOKEN }} TRUNK_DEBUGGER_TOKEN: ${{ secrets.TRUNK_DEBUGGER_TOKEN }} TRUNK_ORG_PROD_TOKEN: ${{ secrets.TRUNK_ORG_PROD_TOKEN }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 0c007b2ea..76df7ea78 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -151,6 +151,7 @@ jobs: with: linter-version: KnownGoodVersion ref-type: main + snyk-token: ${{ secrets.TRUNK_SNYK_TOKEN }} sourcery-token: ${{ secrets.TRUNK_SOURCERY_TOKEN }} append-args: ${{ needs.detect_changes.outputs.all-linters }} ${{ @@ -167,6 +168,7 @@ jobs: with: linter-version: Latest ref-type: main + snyk-token: ${{ secrets.TRUNK_SNYK_TOKEN }} sourcery-token: ${{ secrets.TRUNK_SOURCERY_TOKEN }} append-args: ${{ needs.detect_changes.outputs.linters-files }} trunk-staging-token: ${{ secrets.TRUNK_DEBUGGER_TOKEN }} @@ -262,6 +264,7 @@ jobs: with: linter-version: Latest ref-type: main + snyk-token: ${{ secrets.TRUNK_SNYK_TOKEN }} sourcery-token: ${{ secrets.TRUNK_SOURCERY_TOKEN }} cli-path: ${{ github.workspace }}\trunk.ps1 append-args: ${{needs.detect_changes.outputs.linters-files }} -- --maxWorkers=5 diff --git a/.github/workflows/upload_results.reusable.yaml b/.github/workflows/upload_results.reusable.yaml index 48230fec0..cc61d2232 100644 --- a/.github/workflows/upload_results.reusable.yaml +++ b/.github/workflows/upload_results.reusable.yaml @@ -34,6 +34,8 @@ on: required: false TRUNK_OPEN_PR_APP_PRIVATE_KEY: required: false + TRUNK_SNYK_TOKEN: + required: false TRUNK_SOURCERY_TOKEN: required: false TRUNK_DEBUGGER_TOKEN: @@ -242,6 +244,7 @@ jobs: linter-version: Latest ref-type: main append-args: ${{ needs.upload_test_results.outputs.reruns }} -- -u + snyk-token: ${{ secrets.TRUNK_SNYK_TOKEN }} sourcery-token: ${{ secrets.TRUNK_SOURCERY_TOKEN }} trunk-staging-token: ${{ secrets.TRUNK_DEBUGGER_TOKEN }} trunk-prod-token: ${{ secrets.TRUNK_ORG_PROD_TOKEN }} diff --git a/.github/workflows/windows_nightly.yaml b/.github/workflows/windows_nightly.yaml index 0f060ea7e..68ff0bb43 100644 --- a/.github/workflows/windows_nightly.yaml +++ b/.github/workflows/windows_nightly.yaml @@ -45,6 +45,7 @@ jobs: with: linter-version: ${{ matrix.linter-version }} ref-type: main + snyk-token: ${{ secrets.TRUNK_SNYK_TOKEN }} sourcery-token: ${{ secrets.TRUNK_SOURCERY_TOKEN }} cli-path: ${{ github.workspace }}\trunk.ps1 # manually specify more parallelism to avoid bottlenecks diff --git a/.gitignore b/.gitignore index 026fd7db3..75a65a35c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ node_modules/ out/ junit.xml + +# Snyk +.dccache diff --git a/README.md b/README.md index ad42f489a..aac41e3e5 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ trunk check enable {linter} | Ruby | [brakeman], [rubocop], [rufo], [semgrep], [standardrb] | | Rust | [clippy], [rustfmt] | | Scala | [scalafmt] | -| Security | [checkov], [dustilock], [nancy], [osv-scanner], [tfsec], [trivy], [trufflehog], [terrascan] | +| Security | [checkov], [dustilock], [nancy], [osv-scanner], [snyk], [tfsec], [trivy], [trufflehog], [terrascan] | | SQL | [sqlfluff], [sqlfmt], [sql-formatter], [squawk] | | SVG | [svgo] | | Swift | [stringslint], [swiftlint], [swiftformat] | @@ -175,6 +175,7 @@ trunk check enable {linter} [sqlfluff]: https://github.com/sqlfluff/sqlfluff#readme [sqlfmt]: https://github.com/tconbeer/sqlfmt#readme [squawk]: https://github.com/sbdchd/squawk#readme +[snyk]: https://github.com/snyk/cli#readme [standardrb]: https://github.com/testdouble/standard#readme [stringslint]: https://github.com/dral3x/StringsLint#readme [stylelint]: https://github.com/stylelint/stylelint#readme diff --git a/linters/snyk/plugin.yaml b/linters/snyk/plugin.yaml new file mode 100644 index 000000000..cb23fd187 --- /dev/null +++ b/linters/snyk/plugin.yaml @@ -0,0 +1,66 @@ +version: 0.1 +downloads: + - name: snyk + downloads: + - url: https://downloads.snyk.io/cli/v${version}/snyk-${os}-${cpu} + cpu: arm_64 + os: + macos: macos + linux: linux + - url: https://downloads.snyk.io/cli/v${version}/snyk-${os} + cpu: x86_64 + os: + macos: macos + linux: linux + - url: https://downloads.snyk.io/cli/v${version}/snyk-win.exe + os: windows +tools: + definitions: + - name: snyk + download: snyk + known_good_version: 1.1295.0 + shims: [snyk] + health_checks: + - command: snyk --version + parse_regex: ${semver} +lint: + definitions: + - name: snyk + tools: [snyk] + suggest_if: config_present + description: Security scanning tool for code, dependencies and containers + known_good_version: 1.1295.0 + commands: + - name: test + files: [lockfile] + output: sarif + run: snyk test --sarif --skip-unresolved --file=${target} + success_codes: [0, 1] # Snyk returns 1 when vulnerabilities are found + read_output_from: stdout + batch: false + is_security: true + - name: code + files: [javascript, typescript, java, python] + output: sarif + run: snyk code test --sarif . + run_from: ${parent} + success_codes: [0, 1] + read_output_from: stdout + sandbox_type: copy_targets + batch: true + is_security: true + - name: container + files: [docker] + output: sarif + run: snyk container test --sarif ${target} + success_codes: [0, 1] + read_output_from: stdout + batch: true + is_security: true + direct_configs: [.snyk] + environment: + - name: SNYK_TOKEN + optional: true + value: ${env.SNYK_TOKEN} + - name: PATH + list: ["${linter}", "${env.PATH}"] diff --git a/linters/snyk/snyk.test.ts b/linters/snyk/snyk.test.ts new file mode 100644 index 000000000..f63385374 --- /dev/null +++ b/linters/snyk/snyk.test.ts @@ -0,0 +1,4 @@ +import { customLinterCheckTest } from "tests"; +import { TEST_DATA } from "tests/utils"; + +customLinterCheckTest({ linterName: "snyk", args: TEST_DATA, testName: "basic" }); diff --git a/linters/snyk/test_data/SqlInjectionLess4.java b/linters/snyk/test_data/SqlInjectionLess4.java new file mode 100644 index 000000000..dafab92fd --- /dev/null +++ b/linters/snyk/test_data/SqlInjectionLess4.java @@ -0,0 +1,77 @@ + +/* + * This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/ + * + * Copyright (c) 2002 - 2019 Bruce Mayhew + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Getting Source ============== + * + * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects. + */ + + package org.owasp.webgoat.sql_injection.introduction; + + import org.owasp.webgoat.assignments.AssignmentEndpoint; + import org.owasp.webgoat.assignments.AssignmentHints; + import org.owasp.webgoat.assignments.AttackResult; + import org.springframework.web.bind.annotation.PostMapping; + import org.springframework.web.bind.annotation.RequestParam; + import org.springframework.web.bind.annotation.ResponseBody; + import org.springframework.web.bind.annotation.RestController; + + import javax.sql.DataSource; + import java.sql.*; + + import static java.sql.ResultSet.*; + + + @RestController + @AssignmentHints(value = {"SqlStringInjectionHint4-1", "SqlStringInjectionHint4-2", "SqlStringInjectionHint4-3"}) + public class SqlInjectionLesson4 extends AssignmentEndpoint { + + private final DataSource dataSource; + + public SqlInjectionLesson4(DataSource dataSource) { + this.dataSource = dataSource; + } + + @PostMapping("/SqlInjection/attack4") + @ResponseBody + public AttackResult completed(@RequestParam String query) { + return injectableQuery(query); + } + + protected AttackResult injectableQuery(String query) { + try (Connection connection = dataSource.getConnection()) { + try (Statement statement = connection.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY)) { + statement.executeUpdate(query); + connection.commit(); + ResultSet results = statement.executeQuery("SELECT phone from employees;"); + StringBuffer output = new StringBuffer(); + // user completes lesson if column phone exists + if (results.first()) { + output.append("" + query + ""); + return success(this).output(output.toString()).build(); + } else { + return failed(this).output(output.toString()).build(); + } + } catch (SQLException sqle) { + return failed(this).output(sqle.getMessage()).build(); + } + } catch (Exception e) { + return failed(this).output(this.getClass().getName() + " : " + e.getMessage()).build(); + } + } + } diff --git a/linters/snyk/test_data/index.js b/linters/snyk/test_data/index.js new file mode 100644 index 000000000..e01b12544 --- /dev/null +++ b/linters/snyk/test_data/index.js @@ -0,0 +1,291 @@ +var utils = require('../utils'); +var mongoose = require('mongoose'); +var Todo = mongoose.model('Todo'); +var User = mongoose.model('User'); +// TODO: +var hms = require('humanize-ms'); +var ms = require('ms'); +var streamBuffers = require('stream-buffers'); +var readline = require('readline'); +var moment = require('moment'); +var exec = require('child_process').exec; + +// zip-slip +var fileType = require('file-type'); +var AdmZip = require('adm-zip'); +var fs = require('fs'); + +// prototype-pollution +var _ = require('lodash'); + +exports.index = function (req, res, next) { + Todo. + find({}). + sort('-updated_at'). + exec(function (err, todos) { + if (err) return next(err); + + res.render('index', { + title: 'Goof TODO', + subhead: 'Vulnerabilities at their best', + todos: todos, + }); + }); +}; + + +exports.admin = function (req, res, next) { + console.log(req.body); + User.find({ username: req.body.username, password: req.body.password }, function (err, users) { + if (users.length > 0) { + return res.render('admin', { + title: 'Admin Access Granted', + granted: true, + }); + } else { + return res.render('admin', { + title: 'Admin Access', + granted: false, + }); + } + }); + +}; + +function parse(todo) { + var t = todo; + + var remindToken = ' in '; + var reminder = t.toString().indexOf(remindToken); + if (reminder > 0) { + var time = t.slice(reminder + remindToken.length); + time = time.replace(/\n$/, ''); + + var period = hms(time); + + console.log('period: ' + period); + + // remove it + t = t.slice(0, reminder); + if (typeof period != 'undefined') { + t += ' [' + ms(period) + ']'; + } + } + return t; +} + +exports.create = function (req, res, next) { + // console.log('req.body: ' + JSON.stringify(req.body)); + + var item = req.body.content; + var imgRegex = /\!\[alt text\]\((http.*)\s\".*/; + if (typeof(item) == 'string' && item.match(imgRegex)) { + var url = item.match(imgRegex)[1]; + console.log('found img: ' + url); + + exec('identify ' + url, function (err, stdout, stderr) { + console.log(err); + if (err !== null) { + console.log('Error (' + err + '):' + stderr); + } + }); + + } else { + item = parse(item); + } + + new Todo({ + content: item, + updated_at: Date.now(), + }).save(function (err, todo, count) { + if (err) return next(err); + + /* + res.setHeader('Data', todo.content.toString('base64')); + res.redirect('/'); + */ + + res.setHeader('Location', '/'); + res.status(302).send(todo.content.toString('base64')); + + // res.redirect('/#' + todo.content.toString('base64')); + }); +}; + +exports.destroy = function (req, res, next) { + Todo.findById(req.params.id, function (err, todo) { + + try { + todo.remove(function (err, todo) { + if (err) return next(err); + res.redirect('/'); + }); + } catch(e) { + } + }); +}; + +exports.edit = function(req, res, next) { + Todo. + find({}). + sort('-updated_at'). + exec(function (err, todos) { + if (err) return next(err); + + res.render('edit', { + title : 'TODO', + todos : todos, + current : req.params.id + }); + }); +}; + +exports.update = function(req, res, next) { + Todo.findById(req.params.id, function (err, todo) { + + todo.content = req.body.content; + todo.updated_at = Date.now(); + todo.save(function (err, todo, count) { + if(err) return next(err); + + res.redirect('/'); + }); + }); +}; + +// ** express turns the cookie key to lowercase ** +exports.current_user = function (req, res, next) { + + next(); +}; + +function isBlank(str) { + return (!str || /^\s*$/.test(str)); +} + +exports.import = function (req, res, next) { + if (!req.files) { + res.send('No files were uploaded.'); + return; + } + + var importFile = req.files.importFile; + var data; + var importedFileType = fileType(importFile.data); + var zipFileExt = { ext: "zip", mime: "application/zip" }; + if (importedFileType === null) { + importedFileType = { ext: "txt", mime: "text/plain" }; + } + if (importedFileType["mime"] === zipFileExt["mime"]) { + var zip = AdmZip(importFile.data); + var extracted_path = "/tmp/extracted_files"; + zip.extractAllTo(extracted_path, true); + data = "No backup.txt file found"; + fs.readFile('backup.txt', 'ascii', function(err, data) { + if (!err) { + data = data; + }}); + } else { + data = importFile.data.toString('ascii'); + } + var lines = data.split('\n'); + lines.forEach(function (line) { + var parts = line.split(','); + var what = parts[0]; + console.log('importing ' + what); + var when = parts[1]; + var locale = parts[2]; + var format = parts[3]; + var item = what; + if (!isBlank(what)) { + if (!isBlank(when) && !isBlank(locale) && !isBlank(format)) { + console.log('setting locale ' + parts[1]); + moment.locale(locale); + var d = moment(when); + console.log('formatting ' + d); + item += ' [' + d.format(format) + ']'; + } + + new Todo({ + content: item, + updated_at: Date.now(), + }).save(function (err, todo, count) { + if (err) return next(err); + console.log('added ' + todo); + }); + } + }); + + res.redirect('/'); +}; + +exports.about_new = function (req, res, next) { + console.log(JSON.stringify(req.query)); + return res.render("about_new.dust", + { + title: 'Goof TODO', + subhead: 'Vulnerabilities at their best', + device: req.query.device + }); +}; + +// Prototype Pollution + +/////////////////////////////////////////////////////////////////////////////// +// In order of simplicity we are not using any database. But you can write the +// same logic using MongoDB. +const users = [ + // You know password for the user. + {name: 'user', password: 'pwd'}, + // You don't know password for the admin. + {name: 'admin', password: Math.random().toString(32), canDelete: true}, +]; + +let messages = []; +let lastId = 1; + +function findUser(auth) { + return users.find((u) => + u.name === auth.name && + u.password === auth.password); +} +/////////////////////////////////////////////////////////////////////////////// + +exports.chat = { + get(req, res) { + res.send(messages); + }, + add(req, res) { + const user = findUser(req.body.auth || {}); + + if (!user) { + res.status(403).send({ok: false, error: 'Access denied'}); + return; + } + + const message = { + // Default message icon. Cen be overwritten by user. + icon: '👋', + }; + + _.merge(message, req.body.message, { + id: lastId++, + timestamp: Date.now(), + userName: user.name, + }); + + messages.push(message); + res.send({ok: true}); + }, + delete(req, res) { + const user = findUser(req.body.auth || {}); + + if (!user || !user.canDelete) { + res.status(403).send({ok: false, error: 'Access denied'}); + return; + } + + messages = messages.filter((m) => m.id !== req.body.messageId); + res.send({ok: true}); + } +}; diff --git a/linters/snyk/test_data/requirements.txt b/linters/snyk/test_data/requirements.txt new file mode 100644 index 000000000..4c29e3562 --- /dev/null +++ b/linters/snyk/test_data/requirements.txt @@ -0,0 +1,2 @@ +pillow==9.1.1 +langchain==0.0.171 diff --git a/linters/snyk/test_data/snyk_v1.1295.0_basic.check.shot b/linters/snyk/test_data/snyk_v1.1295.0_basic.check.shot new file mode 100644 index 000000000..2a0c57758 --- /dev/null +++ b/linters/snyk/test_data/snyk_v1.1295.0_basic.check.shot @@ -0,0 +1,298 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Testing linter snyk test basic 1`] = ` +{ + "issues": [ + { + "code": "java/Sqli", + "column": "18", + "file": "test_data/SqlInjectionLess4.java", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "59", + "linter": "snyk", + "message": "Unsanitized input from an HTTP parameter flows into executeUpdate, where it is used in an SQL query. This may result in an SQL Injection vulnerability.", + "ranges": [ + { + "filePath": "test_data/SqlInjectionLess4.java", + "length": "23", + "offset": "2394", + }, + ], + "targetType": "javascript", + }, + { + "code": "javascript/NoSqli", + "column": "8", + "file": "test_data/index.js", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "116", + "linter": "snyk", + "message": "Unsanitized input from an HTTP parameter flows into findById, where it is used in an NoSQL query. This may result in an NoSQL Injection vulnerability.", + "ranges": [ + { + "filePath": "test_data/index.js", + "length": "8", + "offset": "2725", + }, + ], + "targetType": "javascript", + }, + { + "code": "javascript/NoSqli", + "column": "8", + "file": "test_data/index.js", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "144", + "linter": "snyk", + "message": "Unsanitized input from an HTTP parameter flows into findById, where it is used in an NoSQL query. This may result in an NoSQL Injection vulnerability.", + "ranges": [ + { + "filePath": "test_data/index.js", + "length": "8", + "offset": "3261", + }, + ], + "targetType": "javascript", + }, + { + "code": "javascript/NoRateLimitingForExpensiveWebOperation", + "column": "18", + "file": "test_data/index.js", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_MEDIUM", + "line": "166", + "linter": "snyk", + "message": "This endpoint handler performs a file system operation and does not use a rate-limiting mechanism. It may enable the attackers to perform Denial-of-service attacks. Consider using a rate-limiting middleware such as express-limit.", + "ranges": [ + { + "filePath": "test_data/index.js", + "length": "1567", + "offset": "3702", + }, + ], + "targetType": "javascript", + }, + { + "code": "javascript/NoRateLimitingForExpensiveWebOperation", + "column": "21", + "file": "test_data/index.js", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_MEDIUM", + "line": "222", + "linter": "snyk", + "message": "This endpoint handler performs a file system operation and does not use a rate-limiting mechanism. It may enable the attackers to perform Denial-of-service attacks. Consider using a rate-limiting middleware such as express-limit.", + "ranges": [ + { + "filePath": "test_data/index.js", + "length": "242", + "offset": "5292", + }, + ], + "targetType": "javascript", + }, + { + "code": "javascript/NoSqli", + "column": "8", + "file": "test_data/index.js", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "39", + "linter": "snyk", + "message": "Unsanitized input from the HTTP request body flows into find, where it is used in an NoSQL query. This may result in an NoSQL Injection vulnerability.", + "ranges": [ + { + "filePath": "test_data/index.js", + "length": "4", + "offset": "918", + }, + ], + "targetType": "javascript", + }, + { + "code": "javascript/NoRateLimitingForExpensiveWebOperation", + "column": "18", + "file": "test_data/index.js", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_MEDIUM", + "line": "77", + "linter": "snyk", + "message": "This endpoint handler performs a system command execution and does not use a rate-limiting mechanism. It may enable the attackers to perform Denial-of-service attacks. Consider using a rate-limiting middleware such as express-limit.", + "ranges": [ + { + "filePath": "test_data/index.js", + "length": "928", + "offset": "1741", + }, + ], + "targetType": "javascript", + }, + { + "code": "SNYK-PYTHON-PILLOW-3113875", + "column": "1", + "file": "test_data/requirements.txt", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_MEDIUM", + "line": "1", + "linter": "snyk", + "message": "This file introduces a vulnerable pillow package with a medium severity vulnerability.", + "targetType": "lockfile", + }, + { + "code": "SNYK-PYTHON-PILLOW-3113876", + "column": "1", + "file": "test_data/requirements.txt", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_MEDIUM", + "line": "1", + "linter": "snyk", + "message": "This file introduces a vulnerable pillow package with a medium severity vulnerability.", + "targetType": "lockfile", + }, + { + "code": "SNYK-PYTHON-PILLOW-5918878", + "column": "1", + "file": "test_data/requirements.txt", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "1", + "linter": "snyk", + "message": "This file introduces a vulnerable pillow package with a critical severity vulnerability.", + "targetType": "lockfile", + }, + { + "code": "SNYK-PYTHON-PILLOW-6043904", + "column": "1", + "file": "test_data/requirements.txt", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "1", + "linter": "snyk", + "message": "This file introduces a vulnerable pillow package with a high severity vulnerability.", + "targetType": "lockfile", + }, + { + "code": "SNYK-PYTHON-PILLOW-6182918", + "column": "1", + "file": "test_data/requirements.txt", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "1", + "linter": "snyk", + "message": "This file introduces a vulnerable pillow package with a high severity vulnerability.", + "targetType": "lockfile", + }, + { + "code": "SNYK-PYTHON-PILLOW-6219984", + "column": "1", + "file": "test_data/requirements.txt", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "1", + "linter": "snyk", + "message": "This file introduces a vulnerable pillow package with a high severity vulnerability.", + "targetType": "lockfile", + }, + { + "code": "SNYK-PYTHON-PILLOW-6219986", + "column": "1", + "file": "test_data/requirements.txt", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "1", + "linter": "snyk", + "message": "This file introduces a vulnerable pillow package with a high severity vulnerability.", + "targetType": "lockfile", + }, + { + "code": "SNYK-PYTHON-PILLOW-6514866", + "column": "1", + "file": "test_data/requirements.txt", + "isSecurity": true, + "issueClass": "ISSUE_CLASS_EXISTING", + "level": "LEVEL_HIGH", + "line": "1", + "linter": "snyk", + "message": "This file introduces a vulnerable pillow package with a high severity vulnerability.", + "targetType": "lockfile", + }, + ], + "lintActions": [ + { + "command": "code", + "fileGroupName": "java", + "linter": "snyk", + "paths": [ + "test_data/SqlInjectionLess4.java", + ], + "verb": "TRUNK_VERB_CHECK", + }, + { + "command": "code", + "fileGroupName": "javascript", + "linter": "snyk", + "paths": [ + "test_data/index.js", + ], + "verb": "TRUNK_VERB_CHECK", + }, + { + "command": "code", + "fileGroupName": "java", + "linter": "snyk", + "paths": [ + "test_data/SqlInjectionLess4.java", + ], + "upstream": true, + "verb": "TRUNK_VERB_CHECK", + }, + { + "command": "code", + "fileGroupName": "javascript", + "linter": "snyk", + "paths": [ + "test_data/index.js", + ], + "upstream": true, + "verb": "TRUNK_VERB_CHECK", + }, + { + "command": "test", + "fileGroupName": "lockfile", + "linter": "snyk", + "paths": [ + "test_data/requirements.txt", + ], + "verb": "TRUNK_VERB_CHECK", + }, + { + "command": "test", + "fileGroupName": "lockfile", + "linter": "snyk", + "paths": [ + "test_data/requirements.txt", + ], + "upstream": true, + "verb": "TRUNK_VERB_CHECK", + }, + ], + "taskFailures": [], + "unformattedFiles": [], +} +`;